Skip to content

Implement GCE PZID verification to validate TDX quote#108

Open
yanchengchen7 wants to merge 1 commit into
google:mainfrom
yanchengchen7:pzid-ver
Open

Implement GCE PZID verification to validate TDX quote#108
yanchengchen7 wants to merge 1 commit into
google:mainfrom
yanchengchen7:pzid-ver

Conversation

@yanchengchen7

@yanchengchen7 yanchengchen7 commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Adds GCE-specific TDX provenance verification through the new gceprovenance CLI.

  • Adds verify, verify-host, and verify-instance commands.
  • Verify supplied or locally generated QuoteV4 evidence using the repository’s embedded Intel root.
  • Supports challenge binding through quote REPORT_DATA.
  • Extracts PPID from the verified quote and retrieves the GCE host registry document.
  • Resolves GCE instance identity from metadata or an explicit instance resource.
  • Computes the GCE PZID digest and compares it with quote MR_OWNER.
  • Saves the original quote and retrieved host registry JSON for external verification.

Tests

go test ./...
go build ./tools/gceprovenance
Manual GCE TDX CVM testing covered:

  • Local and supplied quote flows.
  • Metadata and explicit instance identity.
  • Matching and mismatching REPORT_DATA challenges.
  • Host registry lookup and output file generation.
  • Expected PZID mismatch before GCE populates MR_OWNER.

@yanchengchen7
yanchengchen7 force-pushed the pzid-ver branch 2 times, most recently from 07538f9 to fef68fb Compare July 8, 2026 17:53
@yanchengchen7
yanchengchen7 requested a review from yawangwang July 10, 2026 18:53
@yawangwang

Copy link
Copy Markdown
Collaborator

This is a larger PR to review, could you add summaries to the PR description?

Comment thread tools/provenance/README.md Outdated
@@ -1,49 +1,124 @@
# `provenance` CLI tool

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revisiting this README.md makes me realize both pzid and ppid checks are specific to gce platform, so could you update the CLI name as something like "gceprovenance" to be more specific?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I renamed it to gceprovenance.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say gce-provenance for readability and convention, unless tdx-tools uses non dash separated tools elsewhere.

But are we sure it's just GCE? I believe GKE uses confidential nodes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point, if the VMX rollout will touch GKE fleet or host PPID registration will support GKE eventually then a more generic name would be better.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yawangwang how about gcpprovenance?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having second thoughts, I think gceprovenance is the better name, because the verified identity is specifically GCE VM. If GKE ever to be supported, probably it has different setup considering it has workload, cluster etc., and we can add gke-provenance at that time.

Comment thread tools/provenance/main.go Outdated
@yanchengchen7
yanchengchen7 force-pushed the pzid-ver branch 2 times, most recently from 5ac9398 to 06fab69 Compare July 13, 2026 18:47
@yanchengchen7

Copy link
Copy Markdown
Collaborator Author

This is a larger PR to review, could you add summaries to the PR description?

Done.

@yawangwang yawangwang left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM, is it possible to test this binary on an actual GCE CVM before merging(not sure how the current rollout goes)

Comment thread gce/metadata.go

// ResourceString returns the canonical GCE instance resource string when the
// numeric project and instance IDs are available.
func (i *InstanceInfo) ResourceString() string {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider implementing Stringer interface https://pkg.go.dev/fmt#Stringer if you want to print a formatted string for a custom type.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I prefer keeping this function, as this format might not be the best representation, like for better readability there is the richer logging LogString().

Comment thread gce/provenance.go
if err != nil {
return nil, nil, fmt.Errorf("read quote file at %s: %w", path, err)
}
quote, err := abi.QuoteToProto(quoteBytes)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since abi.QuoteToProto natively supports both v4 and v5 conversion, it would be good to have v5 support for CLI in case GCE supports TDX v1.5

@yanchengchen7 yanchengchen7 Jul 16, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, QuoteToProto can parse V5, but there is no e2e support or verification. I'd prefer not silently support V5, but make this as a focused follow-up improvement when V5 is fully supported.

Comment thread gce/metadata.go
Comment on lines +125 to +141
zone, err := getMetadata(ctx, client, baseURL, "instance/zone")
if err != nil {
return nil, fmt.Errorf("fetch zone from metadata server: %w", err)
}
projectID, err := getMetadata(ctx, client, baseURL, "project/project-id")
if err != nil {
return nil, fmt.Errorf("fetch project ID from metadata server: %w", err)
}
projectNumber, err := getMetadataUint(ctx, client, baseURL, "project/numeric-project-id")
if err != nil {
return nil, err
}
instanceName, err := getMetadata(ctx, client, baseURL, "instance/name")
if err != nil {
return nil, fmt.Errorf("fetch instance name from metadata server: %w", err)
}
instanceID, err := getMetadataUint(ctx, client, baseURL, "instance/id")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to send single request to get everything we need rather than 5 requests?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it could be done in one request with the recursion param. But it retrieves a lot more metadata that we don't use, and this this host-local request, latency is not an issue.

Comment thread gce/metadata.go Outdated
Comment thread tools/gceprovenance/README.md
Comment thread tools/gceprovenance/README.md
Comment thread gce/metadata_test.go Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants