From cedf267d269871dc788c548b345103433fdccbb3 Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+msanft@users.noreply.github.com> Date: Wed, 3 Jan 2024 14:59:05 +0100 Subject: [PATCH 1/8] cli: support GCP marketplace images --- internal/config/config.go | 7 ++- internal/imagefetcher/imagefetcher.go | 46 +++++++++++++++---- .../internal/provider/image_data_source.go | 4 +- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index b792987ff8..8ed672d602 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -183,6 +183,9 @@ type GCPConfig struct { // description: | // Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage DeployCSIDriver *bool `yaml:"deployCSIDriver" validate:"required"` + // description: | + // Use the specified GCP Marketplace image offering. + UseMarketplaceImage *bool `yaml:"useMarketplaceImage" validate:"omitempty"` } // OpenStackConfig holds config information for OpenStack based Constellation deployments. @@ -349,6 +352,7 @@ func Default() *Config { Zone: "", ServiceAccountKeyPath: "", DeployCSIDriver: toPtr(true), + UseMarketplaceImage: toPtr(false), }, OpenStack: &OpenStackConfig{ DirectDownload: toPtr(true), @@ -699,7 +703,8 @@ func (c *Config) DeployYawolLoadBalancer() bool { // UseMarketplaceImage returns whether a marketplace image should be used. func (c *Config) UseMarketplaceImage() bool { - return c.Provider.Azure != nil && c.Provider.Azure.UseMarketplaceImage != nil && *c.Provider.Azure.UseMarketplaceImage + return (c.Provider.Azure != nil && c.Provider.Azure.UseMarketplaceImage != nil && *c.Provider.Azure.UseMarketplaceImage) || + (c.Provider.GCP != nil && c.Provider.GCP.UseMarketplaceImage != nil && *c.Provider.GCP.UseMarketplaceImage) } // Validate checks the config values and returns validation errors. diff --git a/internal/imagefetcher/imagefetcher.go b/internal/imagefetcher/imagefetcher.go index 044870f553..db577ee006 100644 --- a/internal/imagefetcher/imagefetcher.go +++ b/internal/imagefetcher/imagefetcher.go @@ -18,6 +18,7 @@ import ( "fmt" "io/fs" "regexp" + "strings" "github.com/edgelesssys/constellation/v2/internal/api/fetcher" "github.com/edgelesssys/constellation/v2/internal/api/versionsapi" @@ -52,10 +53,6 @@ func (f *Fetcher) FetchReference(ctx context.Context, return "", fmt.Errorf("parsing config image short path: %w", err) } - if useMarketplaceImage { - return buildMarketplaceImage(ver, provider) - } - imgInfoReq := versionsapi.ImageInfo{ Ref: ver.Ref(), Stream: ver.Stream(), @@ -85,21 +82,54 @@ func (f *Fetcher) FetchReference(ctx context.Context, return "", fmt.Errorf("validating image info file: %w", err) } + if useMarketplaceImage { + return buildMarketplaceImage(marketplaceImagePayload{ + ver: ver, + provider: provider, + attestationVariant: attestationVariant, + imgInfo: imgInfo, + filters: filters(provider, region), + }) + } + return getReferenceFromImageInfo(provider, attestationVariant.String(), imgInfo, filters(provider, region)...) } +// marketplaceImagePayload is a helper struct to pass around the required information to build a marketplace image URI. +type marketplaceImagePayload struct { + ver versionsapi.Version + provider cloudprovider.Provider + attestationVariant variant.Variant + imgInfo versionsapi.ImageInfo + filters []filter +} + // buildMarketplaceImage returns a marketplace image URI for the given CSP and version. -func buildMarketplaceImage(ver versionsapi.Version, provider cloudprovider.Provider) (string, error) { - sv, err := semver.New(ver.Version()) +func buildMarketplaceImage(payload marketplaceImagePayload) (string, error) { + sv, err := semver.New(payload.ver.Version()) if err != nil { return "", fmt.Errorf("parsing image version: %w", err) } - switch provider { + if sv.Prerelease() != "" { + return "", fmt.Errorf("marketplace images are not supported for prerelease versions") + } + + switch payload.provider { case cloudprovider.Azure: + // For Azure, multiple fields of information are required to use marketplace images, + // so we pack them in a custom URI. return mpimage.NewAzureMarketplaceImage(sv).URI(), nil + case cloudprovider.GCP: + // For GCP, we just need to replace the GCP project name (constellation-images) to the public project that + // hosts the marketplace images (mpi-edgeless-systems-public). + imageRef, err := getReferenceFromImageInfo(payload.provider, payload.attestationVariant.String(), payload.imgInfo, payload.filters...) + if err != nil { + return "", fmt.Errorf("getting image reference: %w", err) + } + return strings.Replace(imageRef, "constellation-images", "mpi-edgeless-systems-public", 1), nil default: - return "", fmt.Errorf("marketplace images are not supported for csp %s", provider.String()) + return "", fmt.Errorf("marketplace images are not supported for csp %s", payload.provider.String()) } } diff --git a/terraform-provider-constellation/internal/provider/image_data_source.go b/terraform-provider-constellation/internal/provider/image_data_source.go index 3475e2a6f6..ba279e6b4e 100644 --- a/terraform-provider-constellation/internal/provider/image_data_source.go +++ b/terraform-provider-constellation/internal/provider/image_data_source.go @@ -87,8 +87,8 @@ func (d *ImageDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, }, "csp": newCSPAttributeSchema(), "marketplace_image": schema.BoolAttribute{ - Description: "Whether a marketplace image should be used. Currently only supported for Azure.", - MarkdownDescription: "Whether a marketplace image should be used. Currently only supported for Azure.", + Description: "Whether a marketplace image should be used. Currently only supported for Azure and GCP.", + MarkdownDescription: "Whether a marketplace image should be used. Currently only supported for Azure and GCP.", Optional: true, }, "region": schema.StringAttribute{ From 673a9a5cd923519956afe55650dbab128dfdc15f Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+msanft@users.noreply.github.com> Date: Wed, 3 Jan 2024 14:59:17 +0100 Subject: [PATCH 2/8] ci: support GCP marketplace images --- .github/actions/constellation_create/action.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/actions/constellation_create/action.yml b/.github/actions/constellation_create/action.yml index e009803c94..fa2d8f7e34 100644 --- a/.github/actions/constellation_create/action.yml +++ b/.github/actions/constellation_create/action.yml @@ -113,6 +113,13 @@ runs: yq eval -i "(.provider.azure.useMarketplaceImage) = true" constellation-conf.yaml yq eval -i "(.image) = \"${{ inputs.marketplaceImageVersion }}\"" constellation-conf.yaml + - name: Set marketplace image flag (GCP) + if: inputs.marketplaceImageVersion != '' && inputs.cloudProvider == 'gcp' + shell: bash + run: | + yq eval -i "(.provider.gcp.useMarketplaceImage) = true" constellation-conf.yaml + yq eval -i "(.image) = \"${{ inputs.marketplaceImageVersion }}\"" constellation-conf.yaml + - name: Update measurements for non-stable images if: inputs.fetchMeasurements shell: bash From 62afabbb62979744e9bea18e07dd73c740e34ba0 Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+msanft@users.noreply.github.com> Date: Wed, 3 Jan 2024 14:59:25 +0100 Subject: [PATCH 3/8] docs: support GCP marketplace images --- dev-docs/workflows/marketplace-images.md | 11 ++++++++++- docs/docs/overview/license.md | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/dev-docs/workflows/marketplace-images.md b/dev-docs/workflows/marketplace-images.md index d19e2b250a..5fa2b530f2 100644 --- a/dev-docs/workflows/marketplace-images.md +++ b/dev-docs/workflows/marketplace-images.md @@ -24,4 +24,13 @@ And ensure that the cluster uses a release image (i.e. `.image=vX.Y.Z` in the `c ## GCP -Marketplace Images on GCP are not available yet. +On GCP, to use a marketplace image, ensure that the account is entitled to use marketplace images by Edgeless Systems +by accepting the terms through the [web portal](https://console.cloud.google.com/marketplace/vm/config/edgeless-systems-public/constellation). + +Then, set the VMs to use the marketplace image in the `constellation-conf.yaml` file: + +```bash +yq eval -i ".provider.gcp.useMarketplaceImage = true" constellation-conf.yaml +``` + +And ensure that the cluster uses a release image (i.e. `.image=vX.Y.Z` in the `constellation-conf.yaml` file). Afterwards, proceed with the cluster creation as usual. diff --git a/docs/docs/overview/license.md b/docs/docs/overview/license.md index 9a2ddc8f6f..82afb29d7c 100644 --- a/docs/docs/overview/license.md +++ b/docs/docs/overview/license.md @@ -28,6 +28,6 @@ Enterprise Licenses don't have the above limitations and come with support and a Once you have received your Enterprise License file, place it in your [Constellation workspace](../architecture/orchestration.md#workspaces) in a file named `constellation.license`. -## Azure Marketplace +## CSP Marketplaces -Constellation is available through the Azure Marketplace. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your Azure account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). +Constellation is available through the Marketplaces of Azure and GCP. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your Azure / GCP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). From 2d8b7cf482c65f51bf5d90021c5acc73fd3e5bf3 Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+msanft@users.noreply.github.com> Date: Wed, 3 Jan 2024 16:30:08 +0100 Subject: [PATCH 4/8] bazel: generate --- internal/config/config_doc.go | 7 ++++++- .../docs/data-sources/image.md | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/config/config_doc.go b/internal/config/config_doc.go index dab022b475..b1972a94ea 100644 --- a/internal/config/config_doc.go +++ b/internal/config/config_doc.go @@ -229,7 +229,7 @@ func init() { FieldName: "gcp", }, } - GCPConfigDoc.Fields = make([]encoder.Doc, 5) + GCPConfigDoc.Fields = make([]encoder.Doc, 6) GCPConfigDoc.Fields[0].Name = "project" GCPConfigDoc.Fields[0].Type = "string" GCPConfigDoc.Fields[0].Note = "" @@ -255,6 +255,11 @@ func init() { GCPConfigDoc.Fields[4].Note = "" GCPConfigDoc.Fields[4].Description = "Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage" GCPConfigDoc.Fields[4].Comments[encoder.LineComment] = "Deploy Persistent Disk CSI driver with on-node encryption. For details see: https://docs.edgeless.systems/constellation/architecture/encrypted-storage" + GCPConfigDoc.Fields[5].Name = "useMarketplaceImage" + GCPConfigDoc.Fields[5].Type = "bool" + GCPConfigDoc.Fields[5].Note = "" + GCPConfigDoc.Fields[5].Description = "Use the specified GCP Marketplace image offering." + GCPConfigDoc.Fields[5].Comments[encoder.LineComment] = "Use the specified GCP Marketplace image offering." OpenStackConfigDoc.Type = "OpenStackConfig" OpenStackConfigDoc.Comments[encoder.LineComment] = "OpenStackConfig holds config information for OpenStack based Constellation deployments." diff --git a/terraform-provider-constellation/docs/data-sources/image.md b/terraform-provider-constellation/docs/data-sources/image.md index 2e357495d8..245036503b 100644 --- a/terraform-provider-constellation/docs/data-sources/image.md +++ b/terraform-provider-constellation/docs/data-sources/image.md @@ -36,7 +36,7 @@ See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview ### Optional -- `marketplace_image` (Boolean) Whether a marketplace image should be used. Currently only supported for Azure. +- `marketplace_image` (Boolean) Whether a marketplace image should be used. Currently only supported for Azure and GCP. - `region` (String) Region to retrieve the image for. Only required for AWS. The Constellation OS image must be [replicated to the region](https://docs.edgeless.systems/constellation/workflows/config),and the region must [support AMD SEV-SNP](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/snp-requirements.html), if it is used for Attestation. - `version` (String) Version of the Constellation OS image to use. (e.g. `v2.13.0`). If not set, the provider version value is used. From e21a90e07b4a9f28a3bac5c77549463a5314dd89 Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+msanft@users.noreply.github.com> Date: Mon, 8 Jan 2024 10:34:39 +0100 Subject: [PATCH 5/8] ci: allow GCP for mpi e2e test --- .github/workflows/e2e-test-marketplace-image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/e2e-test-marketplace-image.yml b/.github/workflows/e2e-test-marketplace-image.yml index e89bb4e769..080617e3cc 100644 --- a/.github/workflows/e2e-test-marketplace-image.yml +++ b/.github/workflows/e2e-test-marketplace-image.yml @@ -12,7 +12,7 @@ on: type: choice options: - "azure" - default: "azure" + - "gcp" required: true runner: description: "Architecture of the runner that executes the CLI" From 48e88476de96df29cd5487efecf96e4cee3a7bf2 Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+msanft@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:12:49 +0100 Subject: [PATCH 6/8] Update docs/docs/overview/license.md Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com> --- docs/docs/overview/license.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/overview/license.md b/docs/docs/overview/license.md index 82afb29d7c..c1ea47f176 100644 --- a/docs/docs/overview/license.md +++ b/docs/docs/overview/license.md @@ -30,4 +30,4 @@ Once you have received your Enterprise License file, place it in your [Constella ## CSP Marketplaces -Constellation is available through the Marketplaces of Azure and GCP. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your Azure / GCP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). +Constellation is available through the Marketplaces of Azure and GCP. This allows you to create self-managed Constellation clusters that are billed on a pay-per-use basis (hourly, per vCPU) with your CSP account. You can still get direct support by Edgeless Systems. For more information, please [contact us](https://www.edgeless.systems/enterprise-support/). From 005a21be7af7569d24802e5a467e6652f37c8f7d Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+msanft@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:15:34 +0100 Subject: [PATCH 7/8] terraform-provider: allow GCP MPIs --- .../internal/provider/image_data_source.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terraform-provider-constellation/internal/provider/image_data_source.go b/terraform-provider-constellation/internal/provider/image_data_source.go index ba279e6b4e..afd1acd63d 100644 --- a/terraform-provider-constellation/internal/provider/image_data_source.go +++ b/terraform-provider-constellation/internal/provider/image_data_source.go @@ -128,11 +128,11 @@ func (d *ImageDataSource) ValidateConfig(ctx context.Context, req datasource.Val ) } - // Marketplace image is only supported for Azure - if !data.CSP.Equal(types.StringValue("azure")) && !data.MarketplaceImage.IsNull() { + // Marketplace image is only supported for Azure and GCP + if data.CSP.Equal(types.StringValue("aws")) && !data.MarketplaceImage.IsNull() { resp.Diagnostics.AddAttributeWarning( path.Root("marketplace_image"), - "Marketplace images are currently only supported on Azure", "When another CSP than Azure is used, setting 'marketplace_image' has no effect.", + "Marketplace images are currently only supported on Azure and GCP", "When another CSP than Azure or GCP is used, setting 'marketplace_image' has no effect.", ) } From 466dc8f3c727e71f5f9c3d2c536b711e9092b156 Mon Sep 17 00:00:00 2001 From: Moritz Sanft <58110325+msanft@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:02:45 +0100 Subject: [PATCH 8/8] terraform-provider: fix error message --- .../internal/provider/image_data_source.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/terraform-provider-constellation/internal/provider/image_data_source.go b/terraform-provider-constellation/internal/provider/image_data_source.go index afd1acd63d..44262c20ed 100644 --- a/terraform-provider-constellation/internal/provider/image_data_source.go +++ b/terraform-provider-constellation/internal/provider/image_data_source.go @@ -130,9 +130,9 @@ func (d *ImageDataSource) ValidateConfig(ctx context.Context, req datasource.Val // Marketplace image is only supported for Azure and GCP if data.CSP.Equal(types.StringValue("aws")) && !data.MarketplaceImage.IsNull() { - resp.Diagnostics.AddAttributeWarning( + resp.Diagnostics.AddAttributeError( path.Root("marketplace_image"), - "Marketplace images are currently only supported on Azure and GCP", "When another CSP than Azure or GCP is used, setting 'marketplace_image' has no effect.", + "Marketplace images are currently only supported on Azure and GCP", "When another CSP than Azure or GCP is used, marketplace images are unavailable.", ) }