mirror of
https://github.com/edgelesssys/constellation.git
synced 2024-12-24 23:19:39 -05:00
terraform-provider: enable Azure TDX (#2854)
Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
parent
d58d888f54
commit
78b9b0fc96
3
.github/actions/terraform_apply/action.yml
vendored
3
.github/actions/terraform_apply/action.yml
vendored
@ -20,6 +20,9 @@ runs:
|
||||
"azureSEVSNP")
|
||||
attestationVariant="azure-sev-snp"
|
||||
;;
|
||||
"azureTDX")
|
||||
attestationVariant="azure-tdx"
|
||||
;;
|
||||
"gcpSEVES")
|
||||
attestationVariant="gcp-sev-es"
|
||||
;;
|
||||
|
@ -141,6 +141,7 @@ func (c AzureTrustedLaunch) EqualTo(other AttestationCfg) (bool, error) {
|
||||
func DefaultForAzureTDX() *AzureTDX {
|
||||
return &AzureTDX{
|
||||
Measurements: measurements.DefaultsFor(cloudprovider.Azure, variant.AzureTDX{}),
|
||||
// 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},
|
||||
|
@ -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))
|
||||
|
||||
<a id="nestedatt--image"></a>
|
||||
### 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`
|
||||
|
||||
<a id="nestedatt--attestation--azure_firmware_signer_config"></a>
|
||||
@ -93,3 +96,17 @@ Read-Only:
|
||||
|
||||
- `expected` (String)
|
||||
- `warn_only` (Boolean)
|
||||
|
||||
|
||||
<a id="nestedatt--attestation--tdx"></a>
|
||||
### 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)
|
||||
|
@ -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.
|
||||
|
@ -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))
|
||||
|
||||
<a id="nestedatt--attestation--measurements"></a>
|
||||
### Nested Schema for `attestation.measurements`
|
||||
@ -133,6 +135,20 @@ Optional:
|
||||
- `maa_url` (String)
|
||||
|
||||
|
||||
<a id="nestedatt--attestation--tdx"></a>
|
||||
### 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)
|
||||
|
||||
|
||||
|
||||
<a id="nestedatt--image"></a>
|
||||
### Nested Schema for `image`
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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{
|
||||
|
Loading…
Reference in New Issue
Block a user