constellation/terraform-provider-constellation/internal/provider/shared_attributes.go
Moritz Sanft 913b09aeb8
Support SEV-SNP on GCP (#3011)
* terraform: enable creation of SEV-SNP VMs on GCP

* variant: add SEV-SNP attestation variant

* config: add SEV-SNP config options for GCP

* measurements: add GCP SEV-SNP measurements

* gcp: separate package for SEV-ES

* attestation: add GCP SEV-SNP attestation logic

* gcp: factor out common logic

* choose: add GCP SEV-SNP

* cli: add TF variable passthrough for GCP SEV-SNP variables

* cli: support GCP SEV-SNP for `constellation verify`

* Adjust usage of GCP SEV-SNP throughout codebase

* ci: add GCP SEV-SNP

* terraform-provider: support GCP SEV-SNP

* docs: add GCP SEV-SNP reference

* linter fixes

* gcp: only run test with TPM simulator

* gcp: remove nonsense test

* Update cli/internal/cmd/verify.go

Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>

* Update docs/docs/overview/clouds.md

Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>

* Update terraform-provider-constellation/internal/provider/attestation_data_source_test.go

Co-authored-by: Adrian Stobbe <stobbe.adrian@gmail.com>

* linter fixes

* terraform_provider: correctly pass down CC technology

* config: mark attestationconfigapi as unimplemented

* gcp: fix comments and typos

* snp: use nonce and PK hash in SNP report

* snp: ensure we never use ARK supplied by Issuer (#3025)

* Make sure SNP ARK is always loaded from config, or fetched from AMD KDS
* GCP: Set validator `reportData` correctly

---------

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
Co-authored-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* attestationconfigapi: add GCP to uploading

* snp: use correct cert

Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>

* terraform-provider: enable fetching of attestation config values for GCP SEV-SNP

* linter fixes

---------

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
Signed-off-by: Moritz Sanft <58110325+msanft@users.noreply.github.com>
Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com>
Co-authored-by: Adrian Stobbe <stobbe.adrian@gmail.com>
2024-04-16 18:13:47 +02:00

250 lines
8.8 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package provider
import (
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
)
const (
// attributeInput is the attribute type used for input variables.
attributeInput attributeType = true
// attributeOutput is the attribute type used for output variables.
attributeOutput attributeType = false
)
type attributeType bool
func newAttestationVariantAttributeSchema(t attributeType) schema.Attribute {
isInput := bool(t)
return schema.StringAttribute{
Description: "Attestation variant the image should work with. (e.g. `azure-sev-snp`)",
MarkdownDescription: "Attestation variant the image should work with. Can be one of:\n" +
" * `aws-sev-snp`\n" +
" * `aws-nitro-tpm`\n" +
" * `azure-sev-snp`\n" +
" * `azure-tdx`\n" +
" * `gcp-sev-es`\n" +
" * `gcp-sev-snp`\n" +
" * `qemu-vtpm`\n",
Required: isInput,
Computed: !isInput,
Validators: []validator.String{
stringvalidator.OneOf("aws-sev-snp", "aws-nitro-tpm", "azure-sev-snp", "azure-tdx", "gcp-sev-es", "gcp-sev-snp", "qemu-vtpm"),
},
}
}
func newCSPAttributeSchema() schema.Attribute {
return schema.StringAttribute{
Description: "CSP (Cloud Service Provider) to use. (e.g. `azure`)",
MarkdownDescription: "CSP (Cloud Service Provider) to use. (e.g. `azure`)\n" +
"See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports.",
Required: true,
Validators: []validator.String{
stringvalidator.OneOf("aws", "azure", "gcp", "openstack", "stackit"),
},
}
}
func newMeasurementsAttributeSchema(t attributeType) schema.Attribute {
isInput := bool(t)
return schema.MapNestedAttribute{
Computed: !isInput,
Required: isInput,
NestedObject: schema.NestedAttributeObject{
Attributes: map[string]schema.Attribute{
"expected": schema.StringAttribute{
Required: isInput,
Computed: !isInput,
},
"warn_only": schema.BoolAttribute{
Required: isInput,
Computed: !isInput,
},
},
},
}
}
// measurementAttribute is the measurement attribute's data model.
type measurementAttribute struct {
Expected string `tfsdk:"expected"`
WarnOnly bool `tfsdk:"warn_only"`
}
func newAttestationConfigAttributeSchema(t attributeType) schema.Attribute {
isInput := bool(t)
var additionalDescription string
if isInput {
additionalDescription = " The output of the [constellation_attestation](../data-sources/attestation.md) data source provides sensible defaults. "
}
return schema.SingleNestedAttribute{
Computed: !isInput,
Required: isInput,
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{
Computed: !isInput,
Required: isInput,
},
"tee_version": schema.Int64Attribute{
Computed: !isInput,
Required: isInput,
},
"snp_version": schema.Int64Attribute{
Computed: !isInput,
Required: isInput,
},
"microcode_version": schema.Int64Attribute{
Computed: !isInput,
Required: isInput,
},
"azure_firmware_signer_config": schema.SingleNestedAttribute{
Computed: !isInput,
Optional: isInput,
Attributes: map[string]schema.Attribute{
"accepted_key_digests": schema.ListAttribute{
Computed: !isInput,
Optional: isInput,
ElementType: types.StringType,
},
"enforcement_policy": schema.StringAttribute{
Computed: !isInput,
Optional: isInput,
},
"maa_url": schema.StringAttribute{
Computed: !isInput,
Optional: isInput,
},
},
},
"amd_root_key": schema.StringAttribute{
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),
},
}
}
// attestationAttribute is the attestation attribute's data model.
type attestationAttribute struct {
BootloaderVersion uint8 `tfsdk:"bootloader_version"`
TEEVersion uint8 `tfsdk:"tee_version"`
SNPVersion uint8 `tfsdk:"snp_version"`
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"`
}
// azureSnpFirmwareSignerConfigAttribute is the azure firmware signer config attribute's data model.
type azureSnpFirmwareSignerConfigAttribute struct {
AcceptedKeyDigests []string `tfsdk:"accepted_key_digests"`
EnforcementPolicy string `tfsdk:"enforcement_policy"`
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{
Description: "Constellation OS Image to use on the nodes.",
MarkdownDescription: "Constellation OS Image to use on the nodes.",
Computed: !isInput,
Required: isInput,
Attributes: map[string]schema.Attribute{
"version": schema.StringAttribute{
Description: "Semantic version of the image.",
MarkdownDescription: "Semantic version of the image.",
Computed: !isInput,
Required: isInput,
},
"reference": schema.StringAttribute{
Description: "CSP-specific unique reference to the image. The format differs per CSP.",
MarkdownDescription: "CSP-specific unique reference to the image. The format differs per CSP.",
Computed: !isInput,
Required: isInput,
},
"short_path": schema.StringAttribute{
Description: "CSP-agnostic short path to the image. The format is `vX.Y.Z` for release images and `ref/$GIT_REF/stream/$STREAM/$SEMANTIC_VERSION` for pre-release images.",
MarkdownDescription: "CSP-agnostic short path to the image. The format is `vX.Y.Z` for release images and `ref/$GIT_REF/stream/$STREAM/$SEMANTIC_VERSION` for pre-release images.\n" +
"- `$GIT_REF` is the git reference (i.e. branch name) the image was built on, e.g. `main`.\n" +
"- `$STREAM` is the stream the image was built on, e.g. `nightly`.\n" +
"- `$SEMANTIC_VERSION` is the semantic version of the image, e.g. `vX.Y.Z` or `vX.Y.Z-pre...`.",
Computed: !isInput,
Required: isInput,
},
"marketplace_image": schema.BoolAttribute{
Description: "Whether a marketplace image should be used.",
MarkdownDescription: "Whether a marketplace image should be used.",
Optional: true,
},
},
}
}
// imageAttribute is the image attribute's data model.
type imageAttribute struct {
Reference string `tfsdk:"reference"`
Version string `tfsdk:"version"`
ShortPath string `tfsdk:"short_path"`
MarketplaceImage *bool `tfsdk:"marketplace_image"`
}