diff --git a/.github/actions/terraform_apply/action.yml b/.github/actions/terraform_apply/action.yml
index 2b2cfabce..f66b18ace 100644
--- a/.github/actions/terraform_apply/action.yml
+++ b/.github/actions/terraform_apply/action.yml
@@ -20,6 +20,9 @@ runs:
"azureSEVSNP")
attestationVariant="azure-sev-snp"
;;
+ "azureTDX")
+ attestationVariant="azure-tdx"
+ ;;
"gcpSEVES")
attestationVariant="gcp-sev-es"
;;
diff --git a/internal/config/azure.go b/internal/config/azure.go
index 3573216aa..2b1f29a03 100644
--- a/internal/config/azure.go
+++ b/internal/config/azure.go
@@ -141,12 +141,13 @@ func (c AzureTrustedLaunch) EqualTo(other AttestationCfg) (bool, error) {
func DefaultForAzureTDX() *AzureTDX {
return &AzureTDX{
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTDX{}),
- QESVN: 0,
- PCESVN: 0,
- TEETCBSVN: encoding.HexBytes{0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- QEVendorID: encoding.HexBytes{0x93, 0x9a, 0x72, 0x33, 0xf7, 0x9c, 0x4c, 0xa9, 0x94, 0x0a, 0x0d, 0xb3, 0x95, 0x7f, 0x06, 0x07},
- MRSeam: encoding.HexBytes{0x36, 0x03, 0x04, 0xd3, 0x4a, 0x16, 0xaa, 0xce, 0x0a, 0x18, 0xe0, 0x9a, 0xd2, 0xd0, 0x7d, 0x2b, 0x9f, 0xd3, 0xc1, 0x74, 0x37, 0x8e, 0x5b, 0xf1, 0x08, 0x38, 0x80, 0x79, 0x82, 0x7f, 0x89, 0xff, 0x62, 0xac, 0xc5, 0xf8, 0xc4, 0x73, 0xdd, 0x40, 0x70, 0x63, 0x24, 0x83, 0x4e, 0x20, 0x29, 0x46},
- XFAM: encoding.HexBytes{0xe7, 0x18, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
+ // TODO(AB#3798): Enable latest versioning for Azure TDX
+ QESVN: 0,
+ PCESVN: 0,
+ TEETCBSVN: encoding.HexBytes{0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ QEVendorID: encoding.HexBytes{0x93, 0x9a, 0x72, 0x33, 0xf7, 0x9c, 0x4c, 0xa9, 0x94, 0x0a, 0x0d, 0xb3, 0x95, 0x7f, 0x06, 0x07},
+ MRSeam: encoding.HexBytes{0x36, 0x03, 0x04, 0xd3, 0x4a, 0x16, 0xaa, 0xce, 0x0a, 0x18, 0xe0, 0x9a, 0xd2, 0xd0, 0x7d, 0x2b, 0x9f, 0xd3, 0xc1, 0x74, 0x37, 0x8e, 0x5b, 0xf1, 0x08, 0x38, 0x80, 0x79, 0x82, 0x7f, 0x89, 0xff, 0x62, 0xac, 0xc5, 0xf8, 0xc4, 0x73, 0xdd, 0x40, 0x70, 0x63, 0x24, 0x83, 0x4e, 0x20, 0x29, 0x46},
+ XFAM: encoding.HexBytes{0xe7, 0x18, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00},
IntelRootKey: mustParsePEM(tdxRootPEM),
}
diff --git a/terraform-provider-constellation/docs/data-sources/attestation.md b/terraform-provider-constellation/docs/data-sources/attestation.md
index a8668dfdd..bd578314c 100644
--- a/terraform-provider-constellation/docs/data-sources/attestation.md
+++ b/terraform-provider-constellation/docs/data-sources/attestation.md
@@ -31,6 +31,7 @@ data "constellation_attestation" "test" {
* `aws-sev-snp`
* `aws-nitro-tpm`
* `azure-sev-snp`
+ * `azure-tdx`
* `gcp-sev-es`
- `csp` (String) CSP (Cloud Service Provider) to use. (e.g. `azure`)
See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports.
@@ -43,7 +44,7 @@ See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview
### Read-Only
-- `attestation` (Attributes) Attestation comprises the measurements and SEV-SNP specific parameters. (see [below for nested schema](#nestedatt--attestation))
+- `attestation` (Attributes) Attestation comprises the measurements and CVM specific parameters. (see [below for nested schema](#nestedatt--attestation))
### Nested Schema for `image`
@@ -69,11 +70,13 @@ Read-Only:
- `measurements` (Attributes Map) (see [below for nested schema](#nestedatt--attestation--measurements))
- `microcode_version` (Number)
- `snp_version` (Number)
+- `tdx` (Attributes) (see [below for nested schema](#nestedatt--attestation--tdx))
- `tee_version` (Number)
- `variant` (String) Attestation variant the image should work with. Can be one of:
* `aws-sev-snp`
* `aws-nitro-tpm`
* `azure-sev-snp`
+ * `azure-tdx`
* `gcp-sev-es`
@@ -93,3 +96,17 @@ Read-Only:
- `expected` (String)
- `warn_only` (Boolean)
+
+
+
+### Nested Schema for `attestation.tdx`
+
+Read-Only:
+
+- `intel_root_key` (String)
+- `mr_seam` (String)
+- `pce_svn` (Number)
+- `qe_svn` (Number)
+- `qe_vendor_id` (String)
+- `tee_tcb_svn` (String)
+- `xfam` (String)
diff --git a/terraform-provider-constellation/docs/data-sources/image.md b/terraform-provider-constellation/docs/data-sources/image.md
index 245036503..6d0370eaf 100644
--- a/terraform-provider-constellation/docs/data-sources/image.md
+++ b/terraform-provider-constellation/docs/data-sources/image.md
@@ -30,6 +30,7 @@ data "constellation_image" "example" {
* `aws-sev-snp`
* `aws-nitro-tpm`
* `azure-sev-snp`
+ * `azure-tdx`
* `gcp-sev-es`
- `csp` (String) CSP (Cloud Service Provider) to use. (e.g. `azure`)
See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports.
diff --git a/terraform-provider-constellation/docs/resources/cluster.md b/terraform-provider-constellation/docs/resources/cluster.md
index f00da4bb4..d5deed553 100644
--- a/terraform-provider-constellation/docs/resources/cluster.md
+++ b/terraform-provider-constellation/docs/resources/cluster.md
@@ -63,7 +63,7 @@ resource "constellation_cluster" "azure_example" {
### Required
-- `attestation` (Attributes) Attestation comprises the measurements and SEV-SNP specific parameters. The output of the [constellation_attestation](../data-sources/attestation.md) data source provides sensible defaults. (see [below for nested schema](#nestedatt--attestation))
+- `attestation` (Attributes) Attestation comprises the measurements and CVM specific parameters. The output of the [constellation_attestation](../data-sources/attestation.md) data source provides sensible defaults. (see [below for nested schema](#nestedatt--attestation))
- `constellation_microservice_version` (String) The version of Constellation's microservices used within the cluster.
- `csp` (String) CSP (Cloud Service Provider) to use. (e.g. `azure`)
See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports.
@@ -108,11 +108,13 @@ Required:
* `aws-sev-snp`
* `aws-nitro-tpm`
* `azure-sev-snp`
+ * `azure-tdx`
* `gcp-sev-es`
Optional:
- `azure_firmware_signer_config` (Attributes) (see [below for nested schema](#nestedatt--attestation--azure_firmware_signer_config))
+- `tdx` (Attributes) (see [below for nested schema](#nestedatt--attestation--tdx))
### Nested Schema for `attestation.measurements`
@@ -133,6 +135,20 @@ Optional:
- `maa_url` (String)
+
+### Nested Schema for `attestation.tdx`
+
+Optional:
+
+- `intel_root_key` (String)
+- `mr_seam` (String)
+- `pce_svn` (Number)
+- `qe_svn` (Number)
+- `qe_vendor_id` (String)
+- `tee_tcb_svn` (String)
+- `xfam` (String)
+
+
### Nested Schema for `image`
diff --git a/terraform-provider-constellation/internal/provider/attestation_data_source.go b/terraform-provider-constellation/internal/provider/attestation_data_source.go
index 00afa0fe5..56815ae22 100644
--- a/terraform-provider-constellation/internal/provider/attestation_data_source.go
+++ b/terraform-provider-constellation/internal/provider/attestation_data_source.go
@@ -126,7 +126,7 @@ func (d *AttestationDataSource) ValidateConfig(ctx context.Context, req datasour
return
}
if data.AttestationVariant.Equal(types.StringValue("azure-sev-snp")) && data.MaaURL.IsNull() {
- tflog.Info(ctx, "MAA URL not set, MAA fallback will be unavaiable")
+ tflog.Info(ctx, "MAA URL not set, MAA fallback will be unavailable")
}
}
@@ -172,7 +172,7 @@ func (d *AttestationDataSource) Read(ctx context.Context, req datasource.ReadReq
}
tfAttestation, err := convertToTfAttestation(attestationVariant, snpVersions)
if err != nil {
- resp.Diagnostics.AddError("Converting SNP attestation", err.Error())
+ resp.Diagnostics.AddError("Converting attestation", err.Error())
}
verifyFetcher := measurements.NewVerifyFetcher(sigstore.NewCosignVerifier, d.rekor, d.client)
diff --git a/terraform-provider-constellation/internal/provider/attestation_data_source_test.go b/terraform-provider-constellation/internal/provider/attestation_data_source_test.go
index 567fc55c4..5f08cc91d 100644
--- a/terraform-provider-constellation/internal/provider/attestation_data_source_test.go
+++ b/terraform-provider-constellation/internal/provider/attestation_data_source_test.go
@@ -53,6 +53,38 @@ func TestAccAttestationSource(t *testing.T) {
},
},
},
+ "azure tdx success": {
+ // TODO(v2.15): Use regular image tag instead of pseudo version
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ PreCheck: bazelPreCheck,
+ Steps: []resource.TestStep{
+ {
+ Config: testingConfig + `
+ data "constellation_attestation" "test" {
+ csp = "azure"
+ attestation_variant = "azure-tdx"
+ image = {
+ version = "ref/main/stream/debug/v2.15.0-pre.0.20240124172919-4431ac3233bd"
+ reference = "ref/main/stream/debug/v2.15.0-pre.0.20240124172919-4431ac3233bd"
+ short_path = "ref/main/stream/debug/v2.15.0-pre.0.20240124172919-4431ac3233bd"
+ }
+ insecure = true
+ }
+ `,
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.variant", "azure-tdx"),
+
+ resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.bootloader_version", "0"), // not support for TDX
+ resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.tdx.pce_svn", "0"), // Current default value for TDX
+
+ resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.tdx.intel_root_key", `"-----BEGIN CERTIFICATE-----\nMIICjzCCAjSgAwIBAgIUImUM1lqdNInzg7SVUr9QGzknBqwwCgYIKoZIzj0EAwIw\naDEaMBgGA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENv\ncnBvcmF0aW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJ\nBgNVBAYTAlVTMB4XDTE4MDUyMTEwNDUxMFoXDTQ5MTIzMTIzNTk1OVowaDEaMBgG\nA1UEAwwRSW50ZWwgU0dYIFJvb3QgQ0ExGjAYBgNVBAoMEUludGVsIENvcnBvcmF0\naW9uMRQwEgYDVQQHDAtTYW50YSBDbGFyYTELMAkGA1UECAwCQ0ExCzAJBgNVBAYT\nAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC6nEwMDIYZOj/iPWsCzaEKi7\n1OiOSLRFhWGjbnBVJfVnkY4u3IjkDYYL0MxO4mqsyYjlBalTVYxFP2sJBK5zlKOB\nuzCBuDAfBgNVHSMEGDAWgBQiZQzWWp00ifODtJVSv1AbOScGrDBSBgNVHR8ESzBJ\nMEegRaBDhkFodHRwczovL2NlcnRpZmljYXRlcy50cnVzdGVkc2VydmljZXMuaW50\nZWwuY29tL0ludGVsU0dYUm9vdENBLmRlcjAdBgNVHQ4EFgQUImUM1lqdNInzg7SV\nUr9QGzknBqwwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwCgYI\nKoZIzj0EAwIDSQAwRgIhAOW/5QkR+S9CiSDcNoowLuPRLsWGf/Yi7GSX94BgwTwg\nAiEA4J0lrHoMs+Xo5o/sX6O9QWxHRAvZUGOdRQ7cvqRXaqI=\n-----END CERTIFICATE-----\n"`),
+
+ resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.15.expected", "0000000000000000000000000000000000000000000000000000000000000000"),
+ resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.15.warn_only", "false"),
+ ),
+ },
+ },
+ },
"gcp sev-snp succcess": {
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
PreCheck: bazelPreCheck,
diff --git a/terraform-provider-constellation/internal/provider/convert.go b/terraform-provider-constellation/internal/provider/convert.go
index c5ab4f1fe..552bdcdd2 100644
--- a/terraform-provider-constellation/internal/provider/convert.go
+++ b/terraform-provider-constellation/internal/provider/convert.go
@@ -86,6 +86,38 @@ func convertFromTfAttestationCfg(tfAttestation attestationAttribute, attestation
MicrocodeVersion: newVersion(tfAttestation.MicrocodeVersion),
AMDRootKey: rootKey,
}
+ case variant.AzureTDX{}:
+ var rootKey config.Certificate
+ if err := json.Unmarshal([]byte(tfAttestation.TDX.IntelRootKey), &rootKey); err != nil {
+ return nil, fmt.Errorf("unmarshalling root key: %w", err)
+ }
+ teeTCBSVN, err := hex.DecodeString(tfAttestation.TDX.TEETCBSVN)
+ if err != nil {
+ return nil, fmt.Errorf("decoding tee_tcb_svn: %w", err)
+ }
+ qeVendorID, err := hex.DecodeString(tfAttestation.TDX.QEVendorID)
+ if err != nil {
+ return nil, fmt.Errorf("decoding qe_vendor_id: %w", err)
+ }
+ mrSeam, err := hex.DecodeString(tfAttestation.TDX.MRSeam)
+ if err != nil {
+ return nil, fmt.Errorf("decoding mr_seam: %w", err)
+ }
+ xfam, err := hex.DecodeString(tfAttestation.TDX.XFAM)
+ if err != nil {
+ return nil, fmt.Errorf("decoding xfam: %w", err)
+ }
+
+ attestationConfig = &config.AzureTDX{
+ Measurements: c11nMeasurements,
+ QESVN: tfAttestation.TDX.QESVN,
+ PCESVN: tfAttestation.TDX.PCESVN,
+ TEETCBSVN: teeTCBSVN,
+ QEVendorID: qeVendorID,
+ MRSeam: mrSeam,
+ XFAM: xfam,
+ IntelRootKey: rootKey,
+ }
case variant.GCPSEVES{}:
attestationConfig = &config.GCPSEVES{
Measurements: c11nMeasurements,
@@ -127,6 +159,24 @@ func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfi
return tfAttestation, err
}
tfAttestation.AzureSNPFirmwareSignerConfig = tfFirmwareCfg
+ case variant.AzureTDX{}:
+ tdxCfg := config.DefaultForAzureTDX()
+ certStr, err := certAsString(tdxCfg.IntelRootKey)
+ if err != nil {
+ return tfAttestation, err
+ }
+
+ tfTdxCfg := tdxConfigAttribute{
+ IntelRootKey: certStr,
+ // TODO(AB#3798): Load these values dynamically from our attestation API
+ QESVN: tdxCfg.QESVN,
+ PCESVN: tdxCfg.PCESVN,
+ TEETCBSVN: hex.EncodeToString(tdxCfg.TEETCBSVN),
+ QEVendorID: hex.EncodeToString(tdxCfg.QEVendorID),
+ MRSeam: hex.EncodeToString(tdxCfg.MRSeam),
+ XFAM: hex.EncodeToString(tdxCfg.XFAM),
+ }
+ tfAttestation.TDX = tfTdxCfg
case variant.GCPSEVES{}:
// no additional fields
default:
diff --git a/terraform-provider-constellation/internal/provider/shared_attributes.go b/terraform-provider-constellation/internal/provider/shared_attributes.go
index a31786735..79535a53c 100644
--- a/terraform-provider-constellation/internal/provider/shared_attributes.go
+++ b/terraform-provider-constellation/internal/provider/shared_attributes.go
@@ -30,11 +30,12 @@ func newAttestationVariantAttributeSchema(t attributeType) schema.Attribute {
" * `aws-sev-snp`\n" +
" * `aws-nitro-tpm`\n" +
" * `azure-sev-snp`\n" +
+ " * `azure-tdx`\n" +
" * `gcp-sev-es`\n",
Required: isInput,
Computed: !isInput,
Validators: []validator.String{
- stringvalidator.OneOf("aws-sev-snp", "aws-nitro-tpm", "azure-sev-snp", "gcp-sev-es"),
+ stringvalidator.OneOf("aws-sev-snp", "aws-nitro-tpm", "azure-sev-snp", "azure-tdx", "gcp-sev-es"),
},
}
}
@@ -86,8 +87,8 @@ func newAttestationConfigAttributeSchema(t attributeType) schema.Attribute {
return schema.SingleNestedAttribute{
Computed: !isInput,
Required: isInput,
- MarkdownDescription: "Attestation comprises the measurements and SEV-SNP specific parameters." + additionalDescription,
- Description: "Attestation comprises the measurements and SEV-SNP specific parameters." + additionalDescription,
+ MarkdownDescription: "Attestation comprises the measurements and CVM specific parameters." + additionalDescription,
+ Description: "Attestation comprises the measurements and CVM specific parameters." + additionalDescription,
Attributes: map[string]schema.Attribute{
"variant": newAttestationVariantAttributeSchema(t), // duplicated for convenience in cluster resource
"bootloader_version": schema.Int64Attribute{
@@ -129,6 +130,40 @@ func newAttestationConfigAttributeSchema(t attributeType) schema.Attribute {
Computed: !isInput,
Required: isInput,
},
+ "tdx": schema.SingleNestedAttribute{
+ Computed: !isInput,
+ Optional: isInput,
+ Attributes: map[string]schema.Attribute{
+ "qe_svn": schema.Int64Attribute{
+ Computed: !isInput,
+ Optional: isInput,
+ },
+ "pce_svn": schema.Int64Attribute{
+ Computed: !isInput,
+ Optional: isInput,
+ },
+ "tee_tcb_svn": schema.StringAttribute{
+ Computed: !isInput,
+ Optional: isInput,
+ },
+ "qe_vendor_id": schema.StringAttribute{
+ Computed: !isInput,
+ Optional: isInput,
+ },
+ "mr_seam": schema.StringAttribute{
+ Computed: !isInput,
+ Optional: isInput,
+ },
+ "xfam": schema.StringAttribute{
+ Computed: !isInput,
+ Optional: isInput,
+ },
+ "intel_root_key": schema.StringAttribute{
+ Computed: !isInput,
+ Optional: isInput,
+ },
+ },
+ },
"measurements": newMeasurementsAttributeSchema(t),
},
}
@@ -142,6 +177,7 @@ type attestationAttribute struct {
MicrocodeVersion uint8 `tfsdk:"microcode_version"`
AMDRootKey string `tfsdk:"amd_root_key"`
AzureSNPFirmwareSignerConfig azureSnpFirmwareSignerConfigAttribute `tfsdk:"azure_firmware_signer_config"`
+ TDX tdxConfigAttribute `tfsdk:"tdx"`
Variant string `tfsdk:"variant"`
Measurements map[string]measurementAttribute `tfsdk:"measurements"`
}
@@ -153,6 +189,17 @@ type azureSnpFirmwareSignerConfigAttribute struct {
MAAURL string `tfsdk:"maa_url"`
}
+// tdxConfigAttribute groups the TDX specific attributes for Constellation.
+type tdxConfigAttribute struct {
+ QESVN uint16 `tfsdk:"qe_svn"`
+ PCESVN uint16 `tfsdk:"pce_svn"`
+ TEETCBSVN string `tfsdk:"tee_tcb_svn"`
+ QEVendorID string `tfsdk:"qe_vendor_id"`
+ MRSeam string `tfsdk:"mr_seam"`
+ XFAM string `tfsdk:"xfam"`
+ IntelRootKey string `tfsdk:"intel_root_key"`
+}
+
func newImageAttributeSchema(t attributeType) schema.Attribute {
isInput := bool(t)
return schema.SingleNestedAttribute{