mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-03-28 01:28:26 -04:00
terraform-provider: add usage examples (#2713)
* terraform-provider: add usage example for Azure * terraform-provider: add usage example for AWS * terraform-provider: add usage example for GCP * terraform-provider: update usage example for Azure * terraform-provider: update generated documentation * docs: adjust creation on Azure and link to examples * terraform-provider: unify image in-/output (#2725) * terraform-provider: check for returned error when converting microservices * terraform-provider: use state values for outputs after creation * terraform-provider: ignore invalid upgrades (#2728) --------- Co-authored-by: Daniel Weiße <66256922+daniel-weisse@users.noreply.github.com> Co-authored-by: Thomas Tendyck <51411342+thomasten@users.noreply.github.com>
This commit is contained in:
parent
88d626d302
commit
af791bd221
7
.github/actions/terraform_apply/action.yml
vendored
7
.github/actions/terraform_apply/action.yml
vendored
@ -58,13 +58,13 @@ runs:
|
||||
data "constellation_attestation" "con_attestation" {
|
||||
csp = "${{ inputs.cloudProvider }}"
|
||||
attestation_variant = "${attestationVariant}"
|
||||
image_version = "$(yq '.image' constellation-conf.yaml)"
|
||||
image = data.constellation_image.con_image.image
|
||||
maa_url = "$(yq '.infrastructure.azure.attestationURL' constellation-state.yaml)"
|
||||
insecure = true
|
||||
}
|
||||
|
||||
data "constellation_image" "con_image" {
|
||||
image_version = "$(yq '.image' constellation-conf.yaml)"
|
||||
version = "$(yq '.image' constellation-conf.yaml)"
|
||||
attestation_variant = "${attestationVariant}"
|
||||
csp = "${{ inputs.cloudProvider }}"
|
||||
region = "$(yq '.provider.aws.region' constellation-conf.yaml)"
|
||||
@ -75,8 +75,7 @@ runs:
|
||||
constellation_microservice_version = "$(yq '.microserviceVersion' constellation-conf.yaml)"
|
||||
name = "$(yq '.name' constellation-conf.yaml)"
|
||||
uid = "$(yq '.infrastructure.uid' constellation-state.yaml)"
|
||||
image_reference = data.constellation_image.con_image.reference
|
||||
image_version = "$(yq '.microserviceVersion' constellation-conf.yaml)"
|
||||
image = data.constellation_image.con_image.image
|
||||
attestation = data.constellation_attestation.con_attestation.attestation
|
||||
init_secret = "$(yq '.infrastructure.initSecret' constellation-state.yaml | xxd -r -p)"
|
||||
master_secret = random_bytes.master_secret.hex
|
||||
|
@ -36,6 +36,12 @@ terraform {
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to add the build's pseudo-version (without the `v` prefix) as the `<version>`. Alternatively, check the available versions in your local plugin cache:
|
||||
|
||||
```bash
|
||||
ls ~/.terraform.d/plugins/registry.terraform.io/edgelesssys/constellation
|
||||
```
|
||||
|
||||
Alternatively, you can configure Terraform to use your binary by setting a [development override](https://developer.hashicorp.com/terraform/cli/config/config-file#development-overrides-for-provider-developers),
|
||||
so that the registry path to the provider is replaced with the path to the locally built provider.
|
||||
A `config.tfrc` file containing the necessary configuration can be created with the following commands:
|
||||
|
@ -45,7 +45,7 @@ It's recommended to use Terraform for infrastructure management, but you can use
|
||||
|
||||
:::info
|
||||
|
||||
When using Terraform, you can use the [Terraform provider](./terraform-provider.md) to manage the entire Constellation cluster lifecycle.
|
||||
When using Terraform, you can use the [Constellation Terraform provider](./terraform-provider.md) to manage the entire Constellation cluster lifecycle.
|
||||
|
||||
:::
|
||||
|
||||
|
@ -20,30 +20,75 @@ This example shows how to set up a Constellation cluster with the reference IAM
|
||||
cd constellation-workspace
|
||||
```
|
||||
|
||||
1. Create a `main.tf` file.
|
||||
<!--TODO(elchead): AB#3607 put correct examples, with follow up PR with #2713 examples
|
||||
2. Use one of the [example configurations for using the Constellation Terraform provider](https://github.com/edgelesssys/constellation/tree/main/terraform-provider-constellation/examples/full) or create a `main.tf` file and fill it with the resources you want to create. The [Constellation Terraform provider documentation](https://registry.terraform.io/providers/edgelesssys/constellation/latest) offers thorough documentation on the resources and their attributes.
|
||||
3. Initialize and apply the Terraform configuration.
|
||||
<tabs groupId="csp">
|
||||
|
||||
<tabItem value="azure" label="Azure">
|
||||
</tabItem>
|
||||
When creating a cluster on Azure, you need to manually patch the policy of the MAA provider before creating the Constellation cluster, as this feature isn't available in Azure's Terraform provider yet. The Constellation CLI provides a utility for patching, but you
|
||||
can also do it manually.
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
terraform apply -target module.azure_iam # adjust resource path if not using the example configuration
|
||||
terraform apply -target module.azure_infrastructure # adjust resource path if not using the example configuration
|
||||
constellation maa-patch $(terraform output maa_url) # adjust output path / input if not using the example configuration or manually patch the resource
|
||||
terraform apply -target constellation_cluster.azure_example # adjust resource path if not using the example configuration
|
||||
```
|
||||
|
||||
Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios.
|
||||
|
||||
Use the following policy if manually performing the patch.
|
||||
|
||||
```
|
||||
version= 1.0;
|
||||
authorizationrules
|
||||
{
|
||||
[type=="x-ms-azurevm-default-securebootkeysvalidated", value==false] => deny();
|
||||
[type=="x-ms-azurevm-debuggersdisabled", value==false] => deny();
|
||||
// The line below was edited to use the MAA provider within Constellation. Do not edit manually.
|
||||
//[type=="secureboot", value==false] => deny();
|
||||
[type=="x-ms-azurevm-signingdisabled", value==false] => deny();
|
||||
[type=="x-ms-azurevm-dbvalidated", value==false] => deny();
|
||||
[type=="x-ms-azurevm-dbxvalidated", value==false] => deny();
|
||||
=> permit();
|
||||
};
|
||||
issuancerules
|
||||
{
|
||||
};
|
||||
```
|
||||
</tabItem>
|
||||
<tabItem value="aws" label="AWS">
|
||||
</tabItem>
|
||||
|
||||
<tabItem value="gcp" label="GCP">
|
||||
</tabItem>
|
||||
</tabs>-->
|
||||
|
||||
1. Initialize and apply the file.
|
||||
Initialize the providers and apply the configuration.
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
terraform apply
|
||||
```
|
||||
|
||||
Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios.
|
||||
</tabItem>
|
||||
<tabItem value="gcp" label="GCP">
|
||||
Initialize the providers and apply the configuration.
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
terraform apply
|
||||
```
|
||||
|
||||
Optionally, you can prefix the `terraform apply` command with `TF_LOG=INFO` to collect [Terraform logs](https://developer.hashicorp.com/terraform/internals/debugging) while applying the configuration. This may provide helpful output in debugging scenarios.
|
||||
</tabItem>
|
||||
</tabs>
|
||||
4. Connect to the cluster.
|
||||
|
||||
```bash
|
||||
terraform output -raw kubeconfig > constellation-admin.conf
|
||||
export KUBECONFIG=$(realpath constellation-admin.conf)
|
||||
```
|
||||
|
||||
## Bringing your own infrastructure
|
||||
|
||||
If you need a custom infrastructure setup, you can download the infrastructure / IAM Terraform modules for the respective CSP from the Constellation [GitHub releases](https://github.com/edgelesssys/constellation/releases). You can modify / extend the modules, per your requirements, while keeping the basic functionality intact.
|
||||
Instead of using the example infrastructure used in the [quick setup](#quick-setup), you can also provide your own infrastructure.
|
||||
If you need a starting point for a custom infrastructure setup, you can download the infrastructure / IAM Terraform modules for the respective CSP from the Constellation [GitHub releases](https://github.com/edgelesssys/constellation/releases). You can modify and extend the modules per your requirements, while keeping the basic functionality intact.
|
||||
The module contains:
|
||||
|
||||
- `{csp}`: cloud resources the cluster runs on
|
||||
@ -54,16 +99,16 @@ When upgrading your cluster, make sure to check the Constellation release notes
|
||||
## Cluster upgrades
|
||||
|
||||
:::tip
|
||||
For general information on cluster upgrades, see the [dedicated upgrade page](./upgrade.md).
|
||||
Also see the [general documentation on cluster upgrades](./upgrade.md).
|
||||
:::
|
||||
|
||||
The steps for applying the upgrade are as follows:
|
||||
|
||||
1. Update the version constraint of the Constellation Terraform provider in the `required_providers` block in your Terraform configuration.
|
||||
2. If you explicitly set any of the version attributes of the provider's resources and data sources (e.g. `image_version` or `constellation_microservice_version`), make sure to update them too. Refer to the [version support policy](https://github.com/edgelesssys/constellation/blob/main/dev-docs/workflows/versions-support.md) for more information on how each Constellation version and its dependencies are supported.
|
||||
3. Update the IAM / infrastructure modules.
|
||||
- For [remote address as module source](https://developer.hashicorp.com/terraform/language/modules/sources#fetching-archives-over-http), update the version number inside the address of the `source` field of the infra / IAM module to the target version.
|
||||
- For [local paths as module source](https://developer.hashicorp.com/terraform/language/modules/sources#local-paths), see the changes made in the reference modules since the upgrade's origin version and adjust your infrastructure configuration accordingly.
|
||||
2. If you explicitly set any of the version attributes of the provider's resources and data sources (e.g. `image_version` or `constellation_microservice_version`), make sure to update them too. Refer to Constellation's [version support policy](https://github.com/edgelesssys/constellation/blob/main/dev-docs/workflows/versions-support.md) for more information on how each Constellation version and its dependencies are supported.
|
||||
3. Update the IAM / infrastructure configuration.
|
||||
- For [remote addresses as module sources](https://developer.hashicorp.com/terraform/language/modules/sources#fetching-archives-over-http), update the version number inside the address of the `source` field of the infrastructure / IAM module to the target version.
|
||||
- For [local paths as module sources](https://developer.hashicorp.com/terraform/language/modules/sources#local-paths) or when [providing your own infrastructure](#bringing-your-own-infrastructure), see the changes made in the reference modules since the upgrade's origin version and adjust your infrastructure / IAM configuration accordingly.
|
||||
4. Upgrade the Terraform module and provider dependencies and apply the targeted configuration.
|
||||
|
||||
```bash
|
||||
|
@ -86,7 +86,7 @@ func (a actionFactory) appendNewAction(
|
||||
return compatibility.NewInvalidUpgradeError(
|
||||
currentVersion.String(),
|
||||
configTargetVersion.String(),
|
||||
fmt.Errorf("this CLI only supports installing microservice version %s", newVersion),
|
||||
fmt.Errorf("this Constellation version only supports installing microservice version %s", newVersion),
|
||||
)
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ func (a actionFactory) appendNewAction(
|
||||
return compatibility.NewInvalidUpgradeError(
|
||||
currentVersion.String(),
|
||||
configTargetVersion.String(),
|
||||
fmt.Errorf("this CLI only supports upgrading to microservice version %s", newVersion),
|
||||
fmt.Errorf("this Constellation version only supports upgrading to microservice version %s", newVersion),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -3,12 +3,12 @@
|
||||
page_title: "constellation_attestation Data Source - constellation"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The data source to fetch measurements from a configured cloud provider and image.
|
||||
Data source to fetch an attestation configuration for a given cloud service provider, attestation variant, and OS image.
|
||||
---
|
||||
|
||||
# constellation_attestation (Data Source)
|
||||
|
||||
The data source to fetch measurements from a configured cloud provider and image.
|
||||
Data source to fetch an attestation configuration for a given cloud service provider, attestation variant, and OS image.
|
||||
|
||||
## Example Usage
|
||||
|
||||
@ -32,10 +32,10 @@ data "constellation_attestation" "test" {
|
||||
* `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.
|
||||
- `image` (Attributes) Constellation OS Image to use on the nodes. (see [below for nested schema](#nestedatt--image))
|
||||
|
||||
### Optional
|
||||
|
||||
- `image_version` (String) The image version to use. If not set, the provider version value is used.
|
||||
- `insecure` (Boolean) DON'T USE IN PRODUCTION Skip the signature verification when fetching measurements for the image.
|
||||
- `maa_url` (String) For Azure only, the URL of the Microsoft Azure Attestation service
|
||||
|
||||
@ -43,6 +43,19 @@ See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview
|
||||
|
||||
- `attestation` (Attributes) Attestation comprises the measurements and SEV-SNP specific parameters. (see [below for nested schema](#nestedatt--attestation))
|
||||
|
||||
<a id="nestedatt--image"></a>
|
||||
### Nested Schema for `image`
|
||||
|
||||
Required:
|
||||
|
||||
- `reference` (String) CSP-specific unique reference to the image. The format differs per CSP.
|
||||
- `short_path` (String) 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.
|
||||
- `$GIT_REF` is the git reference (i.e. branch name) the image was built on, e.g. `main`.
|
||||
- `$STREAM` is the stream the image was built on, e.g. `nightly`.
|
||||
- `$SEMANTIC_VERSION` is the semantic version of the image, e.g. `vX.Y.Z` or `vX.Y.Z-pre...`.
|
||||
- `version` (String) Semantic version of the image.
|
||||
|
||||
|
||||
<a id="nestedatt--attestation"></a>
|
||||
### Nested Schema for `attestation`
|
||||
|
||||
|
@ -36,11 +36,23 @@ See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview
|
||||
|
||||
### Optional
|
||||
|
||||
- `image_version` (String) Version of the Constellation OS image to use. (e.g. `v2.13.0`). If not set, the provider version value is used.
|
||||
- `marketplace_image` (Boolean) Whether a marketplace image should be used. Currently only supported for Azure.
|
||||
- `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.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `reference` (String) CSP-specific reference to the image.
|
||||
- `image` (Attributes) Constellation OS Image to use on the nodes. (see [below for nested schema](#nestedatt--image))
|
||||
|
||||
<a id="nestedatt--image"></a>
|
||||
### Nested Schema for `image`
|
||||
|
||||
Read-Only:
|
||||
|
||||
- `reference` (String) CSP-specific unique reference to the image. The format differs per CSP.
|
||||
- `short_path` (String) 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.
|
||||
- `$GIT_REF` is the git reference (i.e. branch name) the image was built on, e.g. `main`.
|
||||
- `$STREAM` is the stream the image was built on, e.g. `nightly`.
|
||||
- `$SEMANTIC_VERSION` is the semantic version of the image, e.g. `vX.Y.Z` or `vX.Y.Z-pre...`.
|
||||
- `version` (String) Semantic version of the image.
|
||||
|
@ -13,23 +13,44 @@ Resource for a Constellation cluster.
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
// Not up-to-date
|
||||
|
||||
data "constellation_attestation" "foo" {} # Fill accordingly for the CSP and attestation variant
|
||||
|
||||
data "constellation_image" "bar" {} # Fill accordingly for the CSP
|
||||
|
||||
resource "constellation_cluster" "aws_example" {
|
||||
csp = "aws"
|
||||
resource "random_bytes" "master_secret" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "master_secret_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "measurement_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "constellation_cluster" "azure_example" {
|
||||
csp = "azure"
|
||||
constellation_microservice_version = "vX.Y.Z"
|
||||
name = "constell"
|
||||
uid = "deadbeef"
|
||||
constellation_microservice_version = "vx.y.z"
|
||||
uid = "..."
|
||||
image = data.constellation_image.bar.image
|
||||
attestation = data.constellation_attestation.foo.attestation
|
||||
init_secret = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
master_secret = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
master_secret_salt = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
init_secret = "..."
|
||||
master_secret = random_bytes.master_secret.hex
|
||||
master_secret_salt = random_bytes.master_secret_salt.hex
|
||||
measurement_salt = random_bytes.measurement_salt.hex
|
||||
out_of_cluster_endpoint = "123.123.123.123"
|
||||
azure = {
|
||||
tenant_id = "..."
|
||||
subscription_id = "..."
|
||||
uami_client_id = "..."
|
||||
uami_resource_id = "..."
|
||||
location = "..."
|
||||
resource_group = "..."
|
||||
load_balancer_name = "..."
|
||||
network_security_group_name = "..."
|
||||
}
|
||||
network_config = {
|
||||
ip_cidr_node = "192.168.176.0/20"
|
||||
ip_cidr_service = "10.96.0.0/12"
|
||||
@ -44,8 +65,7 @@ resource "constellation_cluster" "aws_example" {
|
||||
|
||||
- `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))
|
||||
- `csp` (String) The Cloud Service Provider (CSP) the cluster should run on.
|
||||
- `image_reference` (String) Constellation OS image reference to use in the CSP specific reference format. Use the [`constellation_image`](../data-sources/image.md) data source to find the correct image reference for your CSP.
|
||||
- `image_version` (String) Constellation OS image version to use in the CSP specific reference format. Use the [`constellation_image`](../data-sources/image.md) data source to find the correct image version for your CSP.
|
||||
- `image` (Attributes) Constellation OS Image to use on the nodes. (see [below for nested schema](#nestedatt--image))
|
||||
- `init_secret` (String) Secret used for initialization of the cluster.
|
||||
- `master_secret` (String) Hex-encoded 32-byte master secret for the cluster.
|
||||
- `master_secret_salt` (String) Hex-encoded 32-byte master secret salt for the cluster.
|
||||
@ -68,7 +88,7 @@ resource "constellation_cluster" "aws_example" {
|
||||
### Read-Only
|
||||
|
||||
- `cluster_id` (String) The cluster ID of the cluster.
|
||||
- `kubeconfig` (String) The kubeconfig of the cluster.
|
||||
- `kubeconfig` (String, Sensitive) The kubeconfig of the cluster.
|
||||
- `owner_id` (String) The owner ID of the cluster.
|
||||
|
||||
<a id="nestedatt--attestation"></a>
|
||||
@ -112,6 +132,19 @@ Optional:
|
||||
|
||||
|
||||
|
||||
<a id="nestedatt--image"></a>
|
||||
### Nested Schema for `image`
|
||||
|
||||
Required:
|
||||
|
||||
- `reference` (String) CSP-specific unique reference to the image. The format differs per CSP.
|
||||
- `short_path` (String) 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.
|
||||
- `$GIT_REF` is the git reference (i.e. branch name) the image was built on, e.g. `main`.
|
||||
- `$STREAM` is the stream the image was built on, e.g. `nightly`.
|
||||
- `$SEMANTIC_VERSION` is the semantic version of the image, e.g. `vX.Y.Z` or `vX.Y.Z-pre...`.
|
||||
- `version` (String) Semantic version of the image.
|
||||
|
||||
|
||||
<a id="nestedatt--network_config"></a>
|
||||
### Nested Schema for `network_config`
|
||||
|
||||
|
114
terraform-provider-constellation/examples/full/aws_cluster.tf
Normal file
114
terraform-provider-constellation/examples/full/aws_cluster.tf
Normal file
@ -0,0 +1,114 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
constellation = {
|
||||
source = "edgelesssys/constellation"
|
||||
version = "X.Y.Z"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "3.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
name = "constell"
|
||||
version = "vX.Y.Z"
|
||||
csp = "aws"
|
||||
attestation_variant = "aws-sev-snp"
|
||||
region = "us-east-2"
|
||||
zone = "us-east-2c"
|
||||
|
||||
master_secret = random_bytes.master_secret.hex
|
||||
master_secret_salt = random_bytes.master_secret_salt.hex
|
||||
measurement_salt = random_bytes.measurement_salt.hex
|
||||
}
|
||||
|
||||
resource "random_bytes" "master_secret" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "master_secret_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "measurement_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
module "aws_iam" {
|
||||
// replace $VERSION with the Constellation version you want to use, e.g., v2.14.0
|
||||
source = "https://github.com/edgelesssys/constellation/releases/download/$VERSION/terraform-module.zip//terraform-module/iam/aws"
|
||||
name_prefix = "constell"
|
||||
region = local.region
|
||||
}
|
||||
|
||||
module "aws_infrastructure" {
|
||||
// replace $VERSION with the Constellation version you want to use, e.g., v2.14.0
|
||||
source = "https://github.com/edgelesssys/constellation/releases/download/$VERSION/terraform-module.zip//terraform-module/aws"
|
||||
name = "constell"
|
||||
node_groups = {
|
||||
control_plane_default = {
|
||||
role = "control-plane"
|
||||
instance_type = "m6a.xlarge"
|
||||
disk_size = 30
|
||||
disk_type = "gp3"
|
||||
initial_count = 2
|
||||
zone = local.zone
|
||||
},
|
||||
worker_default = {
|
||||
role = "worker"
|
||||
instance_type = "m6a.xlarge"
|
||||
disk_size = 30
|
||||
disk_type = "gp3"
|
||||
initial_count = 2
|
||||
zone = local.zone
|
||||
}
|
||||
}
|
||||
iam_instance_profile_name_worker_nodes = module.aws_iam.iam_instance_profile_name_worker_nodes
|
||||
iam_instance_profile_name_control_plane = module.aws_iam.iam_instance_profile_name_control_plane
|
||||
image_id = data.constellation_image.bar.image.reference
|
||||
region = local.region
|
||||
zone = local.zone
|
||||
debug = false
|
||||
enable_snp = true
|
||||
custom_endpoint = ""
|
||||
}
|
||||
|
||||
data "constellation_attestation" "foo" {
|
||||
csp = local.csp
|
||||
attestation_variant = local.attestation_variant
|
||||
image = data.constellation_image.bar.image
|
||||
}
|
||||
|
||||
data "constellation_image" "bar" {
|
||||
csp = local.csp
|
||||
attestation_variant = local.attestation_variant
|
||||
version = local.version
|
||||
region = local.region
|
||||
}
|
||||
|
||||
resource "constellation_cluster" "aws_example" {
|
||||
csp = local.csp
|
||||
constellation_microservice_version = local.version
|
||||
name = module.aws_infrastructure.name
|
||||
uid = module.aws_infrastructure.uid
|
||||
image = data.constellation_image.bar.image
|
||||
attestation = data.constellation_attestation.foo.attestation
|
||||
init_secret = module.aws_infrastructure.init_secret
|
||||
master_secret = local.master_secret
|
||||
master_secret_salt = local.master_secret_salt
|
||||
measurement_salt = local.measurement_salt
|
||||
out_of_cluster_endpoint = module.aws_infrastructure.out_of_cluster_endpoint
|
||||
in_cluster_endpoint = module.aws_infrastructure.in_cluster_endpoint
|
||||
network_config = {
|
||||
ip_cidr_node = module.aws_infrastructure.ip_cidr_node
|
||||
ip_cidr_service = "10.96.0.0/12"
|
||||
}
|
||||
}
|
||||
|
||||
output "kubeconfig" {
|
||||
value = constellation_cluster.aws_example.kubeconfig
|
||||
sensitive = true
|
||||
description = "KubeConfig for the Constellation cluster."
|
||||
}
|
124
terraform-provider-constellation/examples/full/azure_cluster.tf
Normal file
124
terraform-provider-constellation/examples/full/azure_cluster.tf
Normal file
@ -0,0 +1,124 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
constellation = {
|
||||
source = "edgelesssys/constellation"
|
||||
version = "X.Y.Z"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "3.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
name = "constell"
|
||||
version = "vX.Y.Z"
|
||||
csp = "azure"
|
||||
attestation_variant = "azure-sev-snp"
|
||||
location = "northeurope"
|
||||
|
||||
master_secret = random_bytes.master_secret.hex
|
||||
master_secret_salt = random_bytes.master_secret_salt.hex
|
||||
measurement_salt = random_bytes.measurement_salt.hex
|
||||
}
|
||||
|
||||
resource "random_bytes" "master_secret" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "master_secret_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "measurement_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
module "azure_iam" {
|
||||
// replace $VERSION with the Constellation version you want to use, e.g., v2.14.0
|
||||
source = "https://github.com/edgelesssys/constellation/releases/download/$VERSION/terraform-module.zip//terraform-module/iam/azure"
|
||||
location = local.location
|
||||
service_principal_name = "${local.name}-test-sp"
|
||||
resource_group_name = "${local.name}-test-rg"
|
||||
}
|
||||
|
||||
module "azure_infrastructure" {
|
||||
// replace $VERSION with the Constellation version you want to use, e.g., v2.14.0
|
||||
source = "https://github.com/edgelesssys/constellation/releases/download/$VERSION/terraform-module.zip//terraform-module/azure"
|
||||
name = local.name
|
||||
user_assigned_identity = module.azure_iam.uami_id
|
||||
node_groups = {
|
||||
control_plane_default = {
|
||||
role = "control-plane"
|
||||
instance_type = "Standard_DC4as_v5"
|
||||
disk_size = 30
|
||||
disk_type = "Premium_LRS"
|
||||
initial_count = 3
|
||||
},
|
||||
worker_default = {
|
||||
role = "worker"
|
||||
instance_type = "Standard_DC4as_v5"
|
||||
disk_size = 30
|
||||
disk_type = "Premium_LRS"
|
||||
initial_count = 2
|
||||
}
|
||||
}
|
||||
location = local.location
|
||||
image_id = data.constellation_image.bar.image.reference
|
||||
resource_group = module.azure_iam.base_resource_group
|
||||
create_maa = true
|
||||
}
|
||||
|
||||
data "constellation_attestation" "foo" {
|
||||
csp = local.csp
|
||||
attestation_variant = local.attestation_variant
|
||||
image = data.constellation_image.bar.image
|
||||
maa_url = module.azure_infrastructure.attestation_url
|
||||
}
|
||||
|
||||
data "constellation_image" "bar" {
|
||||
csp = local.csp
|
||||
attestation_variant = local.attestation_variant
|
||||
version = local.version
|
||||
}
|
||||
|
||||
resource "constellation_cluster" "azure_example" {
|
||||
csp = local.csp
|
||||
constellation_microservice_version = local.version
|
||||
name = module.azure_infrastructure.name
|
||||
uid = module.azure_infrastructure.uid
|
||||
image = data.constellation_image.bar.image
|
||||
attestation = data.constellation_attestation.foo.attestation
|
||||
init_secret = module.azure_infrastructure.init_secret
|
||||
master_secret = local.master_secret
|
||||
master_secret_salt = local.master_secret_salt
|
||||
measurement_salt = local.measurement_salt
|
||||
out_of_cluster_endpoint = module.azure_infrastructure.out_of_cluster_endpoint
|
||||
in_cluster_endpoint = module.azure_infrastructure.in_cluster_endpoint
|
||||
azure = {
|
||||
tenant_id = module.azure_iam.tenant_id
|
||||
subscription_id = module.azure_iam.subscription_id
|
||||
uami_client_id = module.azure_infrastructure.user_assigned_identity_client_id
|
||||
uami_resource_id = module.azure_iam.uami_id
|
||||
location = local.location
|
||||
resource_group = module.azure_iam.base_resource_group
|
||||
load_balancer_name = module.azure_infrastructure.loadbalancer_name
|
||||
network_security_group_name = module.azure_infrastructure.network_security_group_name
|
||||
}
|
||||
network_config = {
|
||||
ip_cidr_node = module.azure_infrastructure.ip_cidr_node
|
||||
ip_cidr_service = "10.96.0.0/12"
|
||||
}
|
||||
}
|
||||
|
||||
output "maa_url" {
|
||||
value = module.azure_infrastructure.attestation_url
|
||||
description = "URL of the MAA provider, required for manual patching."
|
||||
}
|
||||
|
||||
output "kubeconfig" {
|
||||
value = constellation_cluster.azure_example.kubeconfig
|
||||
sensitive = true
|
||||
description = "KubeConfig for the Constellation cluster."
|
||||
}
|
118
terraform-provider-constellation/examples/full/gcp_cluster.tf
Normal file
118
terraform-provider-constellation/examples/full/gcp_cluster.tf
Normal file
@ -0,0 +1,118 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
constellation = {
|
||||
source = "edgelesssys/constellation"
|
||||
version = "X.Y.Z"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "3.6.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locals {
|
||||
name = "constell"
|
||||
version = "vX.Y.Z"
|
||||
csp = "gcp"
|
||||
attestation_variant = "gcp-sev-es"
|
||||
region = "europe-west3"
|
||||
zone = "europe-west3-b"
|
||||
project_id = "constellation-331613"
|
||||
|
||||
master_secret = random_bytes.master_secret.hex
|
||||
master_secret_salt = random_bytes.master_secret_salt.hex
|
||||
measurement_salt = random_bytes.measurement_salt.hex
|
||||
}
|
||||
|
||||
resource "random_bytes" "master_secret" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "master_secret_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "measurement_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
module "gcp_iam" {
|
||||
// replace $VERSION with the Constellation version you want to use, e.g., v2.14.0
|
||||
source = "https://github.com/edgelesssys/constellation/releases/download/$VERSION/terraform-module.zip//terraform-module/iam/gcp"
|
||||
project_id = local.project_id
|
||||
service_account_id = "${local.name}-test-sa"
|
||||
zone = local.zone
|
||||
region = local.region
|
||||
}
|
||||
|
||||
module "gcp_infrastructure" {
|
||||
// replace $VERSION with the Constellation version you want to use, e.g., v2.14.0
|
||||
source = "https://github.com/edgelesssys/constellation/releases/download/$VERSION/terraform-module.zip//terraform-module/gcp"
|
||||
name = local.name
|
||||
node_groups = {
|
||||
control_plane_default = {
|
||||
role = "control-plane"
|
||||
instance_type = "n2d-standard-4"
|
||||
disk_size = 30
|
||||
disk_type = "pd-ssd"
|
||||
initial_count = 2
|
||||
zone = local.zone
|
||||
},
|
||||
worker_default = {
|
||||
role = "worker"
|
||||
instance_type = "n2d-standard-4"
|
||||
disk_size = 30
|
||||
disk_type = "pd-ssd"
|
||||
initial_count = 2
|
||||
zone = local.zone
|
||||
}
|
||||
}
|
||||
image_id = data.constellation_image.bar.image.reference
|
||||
debug = false
|
||||
zone = local.zone
|
||||
region = local.region
|
||||
project = local.project_id
|
||||
}
|
||||
|
||||
data "constellation_attestation" "foo" {
|
||||
csp = local.csp
|
||||
attestation_variant = local.attestation_variant
|
||||
image = data.constellation_image.bar.image
|
||||
}
|
||||
|
||||
data "constellation_image" "bar" {
|
||||
csp = local.csp
|
||||
attestation_variant = local.attestation_variant
|
||||
version = local.version
|
||||
}
|
||||
|
||||
resource "constellation_cluster" "gcp_example" {
|
||||
csp = local.csp
|
||||
constellation_microservice_version = local.version
|
||||
name = module.gcp_infrastructure.name
|
||||
uid = module.gcp_infrastructure.uid
|
||||
image = data.constellation_image.bar.image
|
||||
attestation = data.constellation_attestation.foo.attestation
|
||||
init_secret = module.gcp_infrastructure.init_secret
|
||||
master_secret = local.master_secret
|
||||
master_secret_salt = local.master_secret_salt
|
||||
measurement_salt = local.measurement_salt
|
||||
out_of_cluster_endpoint = module.gcp_infrastructure.out_of_cluster_endpoint
|
||||
in_cluster_endpoint = module.gcp_infrastructure.in_cluster_endpoint
|
||||
gcp = {
|
||||
project_id = module.gcp_infrastructure.project
|
||||
service_account_key = module.gcp_iam.service_account_key
|
||||
}
|
||||
network_config = {
|
||||
ip_cidr_node = module.gcp_infrastructure.ip_cidr_node
|
||||
ip_cidr_service = "10.96.0.0/12"
|
||||
ip_cidr_pod = module.gcp_infrastructure.ip_cidr_pod
|
||||
}
|
||||
}
|
||||
|
||||
output "kubeconfig" {
|
||||
value = constellation_cluster.gcp_example.kubeconfig
|
||||
sensitive = true
|
||||
description = "KubeConfig for the Constellation cluster."
|
||||
}
|
@ -1,20 +1,41 @@
|
||||
// Not up-to-date
|
||||
|
||||
data "constellation_attestation" "foo" {} # Fill accordingly for the CSP and attestation variant
|
||||
|
||||
data "constellation_image" "bar" {} # Fill accordingly for the CSP
|
||||
|
||||
resource "constellation_cluster" "aws_example" {
|
||||
csp = "aws"
|
||||
resource "random_bytes" "master_secret" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "master_secret_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "random_bytes" "measurement_salt" {
|
||||
length = 32
|
||||
}
|
||||
|
||||
resource "constellation_cluster" "azure_example" {
|
||||
csp = "azure"
|
||||
constellation_microservice_version = "vX.Y.Z"
|
||||
name = "constell"
|
||||
uid = "deadbeef"
|
||||
constellation_microservice_version = "vx.y.z"
|
||||
uid = "..."
|
||||
image = data.constellation_image.bar.image
|
||||
attestation = data.constellation_attestation.foo.attestation
|
||||
init_secret = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
master_secret = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
master_secret_salt = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
init_secret = "..."
|
||||
master_secret = random_bytes.master_secret.hex
|
||||
master_secret_salt = random_bytes.master_secret_salt.hex
|
||||
measurement_salt = random_bytes.measurement_salt.hex
|
||||
out_of_cluster_endpoint = "123.123.123.123"
|
||||
azure = {
|
||||
tenant_id = "..."
|
||||
subscription_id = "..."
|
||||
uami_client_id = "..."
|
||||
uami_resource_id = "..."
|
||||
location = "..."
|
||||
resource_group = "..."
|
||||
load_balancer_name = "..."
|
||||
network_security_group_name = "..."
|
||||
}
|
||||
network_config = {
|
||||
ip_cidr_node = "192.168.176.0/20"
|
||||
ip_cidr_service = "10.96.0.0/12"
|
||||
|
@ -15,6 +15,7 @@ go_library(
|
||||
visibility = ["//terraform-provider-constellation:__subpackages__"],
|
||||
deps = [
|
||||
"//internal/api/attestationconfigapi",
|
||||
"//internal/api/versionsapi",
|
||||
"//internal/atls",
|
||||
"//internal/attestation/choose",
|
||||
"//internal/attestation/idkeydigest",
|
||||
@ -22,10 +23,12 @@ go_library(
|
||||
"//internal/attestation/variant",
|
||||
"//internal/cloud/azureshared",
|
||||
"//internal/cloud/cloudprovider",
|
||||
"//internal/compatibility",
|
||||
"//internal/config",
|
||||
"//internal/constants",
|
||||
"//internal/constellation",
|
||||
"//internal/constellation/helm",
|
||||
"//internal/constellation/kubecmd",
|
||||
"//internal/constellation/state",
|
||||
"//internal/grpc/dialer",
|
||||
"//internal/imagefetcher",
|
||||
@ -42,6 +45,8 @@ go_library(
|
||||
"@com_github_hashicorp_terraform_plugin_framework//provider/schema",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//resource",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//resource/schema",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//resource/schema/planmodifier",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//resource/schema/stringplanmodifier",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//schema/validator",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//types",
|
||||
"@com_github_hashicorp_terraform_plugin_framework//types/basetypes",
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
)
|
||||
|
||||
@ -45,7 +46,7 @@ type AttestationDataSource struct {
|
||||
type AttestationDataSourceModel struct {
|
||||
CSP types.String `tfsdk:"csp"`
|
||||
AttestationVariant types.String `tfsdk:"attestation_variant"`
|
||||
ImageVersion types.String `tfsdk:"image_version"`
|
||||
Image types.Object `tfsdk:"image"`
|
||||
MaaURL types.String `tfsdk:"maa_url"`
|
||||
Insecure types.Bool `tfsdk:"insecure"`
|
||||
Attestation types.Object `tfsdk:"attestation"`
|
||||
@ -85,15 +86,13 @@ func (d *AttestationDataSource) Metadata(_ context.Context, req datasource.Metad
|
||||
// Schema returns the schema for the data source.
|
||||
func (d *AttestationDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
// This description is used by the documentation generator and the language server.
|
||||
MarkdownDescription: "The data source to fetch measurements from a configured cloud provider and image.",
|
||||
Description: "Data source to fetch an attestation configuration for a given cloud service provider, attestation variant, and OS image.",
|
||||
MarkdownDescription: "Data source to fetch an attestation configuration for a given cloud service provider, attestation variant, and OS image.",
|
||||
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"csp": newCSPAttribute(),
|
||||
"attestation_variant": newAttestationVariantAttribute(attributeInput),
|
||||
"image_version": schema.StringAttribute{
|
||||
MarkdownDescription: "The image version to use. If not set, the provider version value is used.",
|
||||
Optional: true,
|
||||
},
|
||||
"csp": newCSPAttributeSchema(),
|
||||
"attestation_variant": newAttestationVariantAttributeSchema(attributeInput),
|
||||
"image": newImageAttributeSchema(attributeInput),
|
||||
"maa_url": schema.StringAttribute{
|
||||
MarkdownDescription: "For Azure only, the URL of the Microsoft Azure Attestation service",
|
||||
Optional: true,
|
||||
@ -102,7 +101,7 @@ func (d *AttestationDataSource) Schema(_ context.Context, _ datasource.SchemaReq
|
||||
MarkdownDescription: "DON'T USE IN PRODUCTION Skip the signature verification when fetching measurements for the image.",
|
||||
Optional: true,
|
||||
},
|
||||
"attestation": newAttestationConfigAttribute(attributeOutput),
|
||||
"attestation": newAttestationConfigAttributeSchema(attributeOutput),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -175,12 +174,15 @@ func (d *AttestationDataSource) Read(ctx context.Context, req datasource.ReadReq
|
||||
}
|
||||
verifyFetcher := measurements.NewVerifyFetcher(sigstore.NewCosignVerifier, d.rekor, d.client)
|
||||
|
||||
imageVersion := data.ImageVersion.ValueString()
|
||||
if imageVersion == "" {
|
||||
tflog.Info(ctx, fmt.Sprintf("No image version specified, using provider version %s", d.version))
|
||||
imageVersion = d.version // Use provider version as default.
|
||||
// parse OS image version
|
||||
var image imageAttribute
|
||||
convertDiags := data.Image.As(ctx, &image, basetypes.ObjectAsOptions{})
|
||||
resp.Diagnostics.Append(convertDiags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
fetchedMeasurements, err := verifyFetcher.FetchAndVerifyMeasurements(ctx, imageVersion,
|
||||
|
||||
fetchedMeasurements, err := verifyFetcher.FetchAndVerifyMeasurements(ctx, image.ShortPath,
|
||||
csp, attestationVariant, insecureFetch)
|
||||
if err != nil {
|
||||
var rekErr *measurements.RekorError
|
||||
|
@ -17,32 +17,6 @@ func TestAccAttestationSource(t *testing.T) {
|
||||
bazelPreCheck := func() { bazelSetTerraformBinaryPath(t) }
|
||||
|
||||
testCases := map[string]resource.TestCase{
|
||||
"aws sev-snp succcess without explicit image_version": {
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactoriesWithVersion("v2.13.0"), // do this to test if a valid default version is set
|
||||
PreCheck: bazelPreCheck,
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testingConfig + `
|
||||
data "constellation_attestation" "test" {
|
||||
csp = "aws"
|
||||
attestation_variant = "aws-sev-snp"
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.variant", "aws-sev-snp"),
|
||||
|
||||
resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.bootloader_version", "3"),
|
||||
resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.microcode_version", "209"),
|
||||
resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.snp_version", "20"),
|
||||
resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.tee_version", "0"),
|
||||
resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.amd_root_key", "\"-----BEGIN CERTIFICATE-----\\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\\nAFZEAwoKCQ==\\n-----END CERTIFICATE-----\\n\""),
|
||||
|
||||
resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.0.expected", "7b068c0c3ac29afe264134536b9be26f1d4ccd575b88d3c3ceabf36ac99c0278"),
|
||||
resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.0.warn_only", "true"),
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
"azure sev-snp success": {
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
|
||||
PreCheck: bazelPreCheck,
|
||||
@ -52,7 +26,11 @@ func TestAccAttestationSource(t *testing.T) {
|
||||
data "constellation_attestation" "test" {
|
||||
csp = "azure"
|
||||
attestation_variant = "azure-sev-snp"
|
||||
image_version = "v2.13.0"
|
||||
image = {
|
||||
version = "v2.13.0"
|
||||
reference = "v2.13.0"
|
||||
short_path = "v2.13.0"
|
||||
}
|
||||
maa_url = "https://www.example.com"
|
||||
}
|
||||
`,
|
||||
@ -84,7 +62,11 @@ func TestAccAttestationSource(t *testing.T) {
|
||||
data "constellation_attestation" "test" {
|
||||
csp = "gcp"
|
||||
attestation_variant = "gcp-sev-es"
|
||||
image_version = "v2.13.0"
|
||||
image = {
|
||||
version = "v2.13.0"
|
||||
reference = "v2.13.0"
|
||||
short_path = "v2.13.0"
|
||||
}
|
||||
}
|
||||
`,
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
|
@ -24,10 +24,12 @@ import (
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/azureshared"
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
"github.com/edgelesssys/constellation/v2/internal/compatibility"
|
||||
"github.com/edgelesssys/constellation/v2/internal/config"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constants"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constellation"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constellation/helm"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constellation/kubecmd"
|
||||
"github.com/edgelesssys/constellation/v2/internal/constellation/state"
|
||||
"github.com/edgelesssys/constellation/v2/internal/grpc/dialer"
|
||||
"github.com/edgelesssys/constellation/v2/internal/kms/uri"
|
||||
@ -37,6 +39,8 @@ import (
|
||||
"github.com/hashicorp/terraform-plugin-framework/path"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
||||
"github.com/hashicorp/terraform-plugin-log/tflog"
|
||||
@ -63,8 +67,7 @@ type ClusterResourceModel struct {
|
||||
Name types.String `tfsdk:"name"`
|
||||
CSP types.String `tfsdk:"csp"`
|
||||
UID types.String `tfsdk:"uid"`
|
||||
ImageVersion types.String `tfsdk:"image_version"`
|
||||
ImageReference types.String `tfsdk:"image_reference"`
|
||||
Image types.Object `tfsdk:"image"`
|
||||
KubernetesVersion types.String `tfsdk:"kubernetes_version"`
|
||||
MicroserviceVersion types.String `tfsdk:"constellation_microservice_version"`
|
||||
OutOfClusterEndpoint types.String `tfsdk:"out_of_cluster_endpoint"`
|
||||
@ -85,19 +88,22 @@ type ClusterResourceModel struct {
|
||||
KubeConfig types.String `tfsdk:"kubeconfig"`
|
||||
}
|
||||
|
||||
type networkConfig struct {
|
||||
// networkConfigAttribute is the network config attribute's data model.
|
||||
type networkConfigAttribute struct {
|
||||
IPCidrNode string `tfsdk:"ip_cidr_node"`
|
||||
IPCidrPod string `tfsdk:"ip_cidr_pod"`
|
||||
IPCidrService string `tfsdk:"ip_cidr_service"`
|
||||
}
|
||||
|
||||
type gcp struct {
|
||||
// gcpAttribute is the gcp attribute's data model.
|
||||
type gcpAttribute struct {
|
||||
// ServiceAccountKey is the private key of the service account used within the cluster.
|
||||
ServiceAccountKey string `tfsdk:"service_account_key"`
|
||||
ProjectID string `tfsdk:"project_id"`
|
||||
}
|
||||
|
||||
type azure struct {
|
||||
// azureAttribute is the azure attribute's data model.
|
||||
type azureAttribute struct {
|
||||
TenantID string `tfsdk:"tenant_id"`
|
||||
Location string `tfsdk:"location"`
|
||||
UamiClientID string `tfsdk:"uami_client_id"`
|
||||
@ -108,6 +114,11 @@ type azure struct {
|
||||
LoadBalancerName string `tfsdk:"load_balancer_name"`
|
||||
}
|
||||
|
||||
// extraMicroservicesAttribute is the extra microservices attribute's data model.
|
||||
type extraMicroservicesAttribute struct {
|
||||
CSIDriver bool `tfsdk:"csi_driver"`
|
||||
}
|
||||
|
||||
// Metadata returns the metadata of the resource.
|
||||
func (r *ClusterResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_cluster"
|
||||
@ -136,16 +147,7 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
||||
Description: "The UID of the cluster.",
|
||||
Required: true,
|
||||
},
|
||||
"image_version": schema.StringAttribute{
|
||||
MarkdownDescription: "Constellation OS image version to use in the CSP specific reference format. Use the [`constellation_image`](../data-sources/image.md) data source to find the correct image version for your CSP.",
|
||||
Description: "Constellation OS image version to use in the CSP specific reference format. Use the `constellation_image` data source to find the correct image version for your CSP.",
|
||||
Required: true,
|
||||
},
|
||||
"image_reference": schema.StringAttribute{
|
||||
MarkdownDescription: "Constellation OS image reference to use in the CSP specific reference format. Use the [`constellation_image`](../data-sources/image.md) data source to find the correct image reference for your CSP.",
|
||||
Description: "Constellation OS image reference to use in the CSP specific reference format. Use the `constellation_image` data source to find the correct image reference for your CSP.",
|
||||
Required: true,
|
||||
},
|
||||
"image": newImageAttributeSchema(attributeInput),
|
||||
"kubernetes_version": schema.StringAttribute{
|
||||
MarkdownDescription: fmt.Sprintf("The Kubernetes version to use for the cluster. When not set, version %s is used. The supported versions are %s.", versions.Default, versions.SupportedK8sVersions()),
|
||||
Description: fmt.Sprintf("The Kubernetes version to use for the cluster. When not set, version %s is used. The supported versions are %s.", versions.Default, versions.SupportedK8sVersions()),
|
||||
@ -227,7 +229,7 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
||||
Description: "Secret used for initialization of the cluster.",
|
||||
Required: true,
|
||||
},
|
||||
"attestation": newAttestationConfigAttribute(attributeInput),
|
||||
"attestation": newAttestationConfigAttributeSchema(attributeInput),
|
||||
"gcp": schema.SingleNestedAttribute{
|
||||
MarkdownDescription: "GCP-specific configuration.",
|
||||
Description: "GCP-specific configuration.",
|
||||
@ -298,16 +300,29 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re
|
||||
MarkdownDescription: "The owner ID of the cluster.",
|
||||
Description: "The owner ID of the cluster.",
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
// We know that this value will never change after creation, so we can use the state value for upgrades.
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"cluster_id": schema.StringAttribute{
|
||||
MarkdownDescription: "The cluster ID of the cluster.",
|
||||
Description: "The cluster ID of the cluster.",
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
// We know that this value will never change after creation, so we can use the state value for upgrades.
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"kubeconfig": schema.StringAttribute{
|
||||
MarkdownDescription: "The kubeconfig of the cluster.",
|
||||
Description: "The kubeconfig of the cluster.",
|
||||
Computed: true,
|
||||
Sensitive: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
// We know that this value will never change after creation, so we can use the state value for upgrades.
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -510,7 +525,7 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel,
|
||||
}
|
||||
|
||||
// parse network config
|
||||
var networkCfg networkConfig
|
||||
var networkCfg networkConfigAttribute
|
||||
convertDiags = data.NetworkConfig.As(ctx, &networkCfg, basetypes.ObjectAsOptions{
|
||||
UnhandledNullAsEmpty: true, // we want to allow null values, as some of the field's subfields are optional.
|
||||
})
|
||||
@ -520,7 +535,7 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel,
|
||||
}
|
||||
|
||||
// parse Constellation microservice config
|
||||
var microserviceCfg extraMicroservices
|
||||
var microserviceCfg extraMicroservicesAttribute
|
||||
convertDiags = data.ExtraMicroservices.As(ctx, µserviceCfg, basetypes.ObjectAsOptions{
|
||||
UnhandledNullAsEmpty: true, // we want to allow null values, as the CSIDriver field is optional
|
||||
})
|
||||
@ -547,19 +562,25 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel,
|
||||
}
|
||||
|
||||
// parse OS image version
|
||||
imageVersion, err := semver.New(data.ImageVersion.ValueString())
|
||||
var image imageAttribute
|
||||
convertDiags = data.Image.As(ctx, &image, basetypes.ObjectAsOptions{})
|
||||
diags.Append(convertDiags...)
|
||||
if diags.HasError() {
|
||||
return diags
|
||||
}
|
||||
imageSemver, err := semver.New(image.Version)
|
||||
if err != nil {
|
||||
diags.AddAttributeError(
|
||||
path.Root("image_version"),
|
||||
path.Root("image").AtName("version"),
|
||||
"Invalid image version",
|
||||
fmt.Sprintf("Parsing image version: %s", err))
|
||||
fmt.Sprintf("Parsing image version (%s): %s", image.Version, err))
|
||||
return diags
|
||||
}
|
||||
|
||||
// Parse in-cluster service account info.
|
||||
serviceAccPayload := constellation.ServiceAccountPayload{}
|
||||
var gcpConfig gcp
|
||||
var azureConfig azure
|
||||
var gcpConfig gcpAttribute
|
||||
var azureConfig azureAttribute
|
||||
switch csp {
|
||||
case cloudprovider.GCP:
|
||||
convertDiags = data.GCP.As(ctx, &gcpConfig, basetypes.ObjectAsOptions{})
|
||||
@ -717,17 +738,28 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel,
|
||||
if !skipNodeUpgrade {
|
||||
// Upgrade node image
|
||||
err = applier.UpgradeNodeImage(ctx,
|
||||
imageVersion,
|
||||
data.ImageReference.ValueString(),
|
||||
imageSemver,
|
||||
image.Reference,
|
||||
false)
|
||||
if err != nil {
|
||||
diags.AddError("Upgrading node OS image", err.Error())
|
||||
var upgradeImageErr *compatibility.InvalidUpgradeError
|
||||
switch {
|
||||
case errors.Is(err, kubecmd.ErrInProgress):
|
||||
diags.AddWarning("Skipping OS image upgrade", "Another upgrade is already in progress.")
|
||||
case errors.As(err, &upgradeImageErr):
|
||||
diags.AddWarning("Ignoring invalid OS image upgrade", err.Error())
|
||||
case err != nil:
|
||||
diags.AddError("Upgrading OS image", err.Error())
|
||||
return diags
|
||||
}
|
||||
|
||||
// Upgrade Kubernetes version
|
||||
if err := applier.UpgradeKubernetesVersion(ctx, k8sVersion, false); err != nil {
|
||||
diags.AddError("Upgrading Kubernetes version", err.Error())
|
||||
// Upgrade Kubernetes components
|
||||
err = applier.UpgradeKubernetesVersion(ctx, k8sVersion, false)
|
||||
var upgradeK8sErr *compatibility.InvalidUpgradeError
|
||||
switch {
|
||||
case errors.As(err, &upgradeK8sErr):
|
||||
diags.AddWarning("Ignoring invalid Kubernetes components upgrade", err.Error())
|
||||
case err != nil:
|
||||
diags.AddError("Upgrading Kubernetes components", err.Error())
|
||||
return diags
|
||||
}
|
||||
}
|
||||
@ -741,9 +773,9 @@ type initRPCPayload struct {
|
||||
masterSecret uri.MasterSecret // master secret of the cluster.
|
||||
measurementSalt []byte // measurement salt of the cluster.
|
||||
apiServerCertSANs []string // additional SANs to add to the API server certificate.
|
||||
azureCfg azure // Azure-specific configuration.
|
||||
gcpCfg gcp // GCP-specific configuration.
|
||||
networkCfg networkConfig // network configuration of the cluster.
|
||||
azureCfg azureAttribute // Azure-specific configuration.
|
||||
gcpCfg gcpAttribute // GCP-specific configuration.
|
||||
networkCfg networkConfigAttribute // network configuration of the cluster.
|
||||
maaURL string // URL of the MAA service. Only used for Azure clusters.
|
||||
k8sVersion versions.ValidK8sVersion // Kubernetes version of the cluster.
|
||||
// Internal Endpoint of the cluster.
|
||||
@ -822,9 +854,13 @@ func (r *ClusterResource) applyHelmCharts(ctx context.Context, applier *constell
|
||||
|
||||
executor, _, err := applier.PrepareHelmCharts(options, state,
|
||||
payload.serviceAccURI, payload.masterSecret, nil)
|
||||
var upgradeErr *compatibility.InvalidUpgradeError
|
||||
if err != nil {
|
||||
diags.AddError("Preparing Helm charts", err.Error())
|
||||
return diags
|
||||
if !errors.As(err, &upgradeErr) {
|
||||
diags.AddError("Upgrading microservices", err.Error())
|
||||
return diags
|
||||
}
|
||||
diags.AddWarning("Ignoring invalid microservice upgrade(s)", err.Error())
|
||||
}
|
||||
|
||||
if err := executor.Apply(ctx); err != nil {
|
||||
@ -845,7 +881,7 @@ type attestationInput struct {
|
||||
// used by the Constellation library.
|
||||
func (r *ClusterResource) convertAttestationConfig(ctx context.Context, data ClusterResourceModel) (attestationInput, diag.Diagnostics) {
|
||||
diags := diag.Diagnostics{}
|
||||
var tfAttestation attestation
|
||||
var tfAttestation attestationAttribute
|
||||
castDiags := data.Attestation.As(ctx, &tfAttestation, basetypes.ObjectAsOptions{})
|
||||
diags.Append(castDiags...)
|
||||
if diags.HasError() {
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
// constellation struct: used to call the constellation API
|
||||
|
||||
// convertFromTfAttestationCfg converts the related terraform struct to a constellation attestation config.
|
||||
func convertFromTfAttestationCfg(tfAttestation attestation, attestationVariant variant.Variant) (config.AttestationCfg, error) {
|
||||
func convertFromTfAttestationCfg(tfAttestation attestationAttribute, attestationVariant variant.Variant) (config.AttestationCfg, error) {
|
||||
c11nMeasurements := make(measurements.M)
|
||||
for strIdx, v := range tfAttestation.Measurements {
|
||||
idx, err := strconv.ParseUint(strIdx, 10, 32)
|
||||
@ -97,8 +97,8 @@ func convertFromTfAttestationCfg(tfAttestation attestation, attestationVariant v
|
||||
}
|
||||
|
||||
// convertToTfAttestationCfg converts the constellation attestation config to the related terraform structs.
|
||||
func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfigapi.SEVSNPVersionAPI) (tfAttestation attestation, err error) {
|
||||
tfAttestation = attestation{
|
||||
func convertToTfAttestation(attVar variant.Variant, snpVersions attestationconfigapi.SEVSNPVersionAPI) (tfAttestation attestationAttribute, err error) {
|
||||
tfAttestation = attestationAttribute{
|
||||
Variant: attVar.String(),
|
||||
BootloaderVersion: snpVersions.Bootloader,
|
||||
TEEVersion: snpVersions.TEE,
|
||||
@ -144,16 +144,16 @@ func certAsString(cert config.Certificate) (string, error) {
|
||||
}
|
||||
|
||||
// convertToTfFirmwareCfg converts the constellation firmware config to the terraform struct.
|
||||
func convertToTfFirmwareCfg(firmwareCfg config.SNPFirmwareSignerConfig) (azureSnpFirmwareSignerConfig, error) {
|
||||
func convertToTfFirmwareCfg(firmwareCfg config.SNPFirmwareSignerConfig) (azureSnpFirmwareSignerConfigAttribute, error) {
|
||||
keyDigestAny, err := firmwareCfg.AcceptedKeyDigests.MarshalYAML()
|
||||
if err != nil {
|
||||
return azureSnpFirmwareSignerConfig{}, err
|
||||
return azureSnpFirmwareSignerConfigAttribute{}, err
|
||||
}
|
||||
keyDigest, ok := keyDigestAny.([]string)
|
||||
if !ok {
|
||||
return azureSnpFirmwareSignerConfig{}, fmt.Errorf("reading Accepted Key Digests: could not convert %T to []string", keyDigestAny)
|
||||
return azureSnpFirmwareSignerConfigAttribute{}, fmt.Errorf("reading Accepted Key Digests: could not convert %T to []string", keyDigestAny)
|
||||
}
|
||||
return azureSnpFirmwareSignerConfig{
|
||||
return azureSnpFirmwareSignerConfigAttribute{
|
||||
AcceptedKeyDigests: keyDigest,
|
||||
EnforcementPolicy: firmwareCfg.EnforcementPolicy.String(),
|
||||
MAAURL: firmwareCfg.MAAURL,
|
||||
@ -161,7 +161,7 @@ func convertToTfFirmwareCfg(firmwareCfg config.SNPFirmwareSignerConfig) (azureSn
|
||||
}
|
||||
|
||||
// convertFromTfFirmwareCfg converts the terraform struct to a constellation firmware config.
|
||||
func convertFromTfFirmwareCfg(tfFirmwareCfg azureSnpFirmwareSignerConfig) (config.SNPFirmwareSignerConfig, error) {
|
||||
func convertFromTfFirmwareCfg(tfFirmwareCfg azureSnpFirmwareSignerConfigAttribute) (config.SNPFirmwareSignerConfig, error) {
|
||||
keyDigests, err := idkeydigest.UnmarshalHexString(tfFirmwareCfg.AcceptedKeyDigests)
|
||||
if err != nil {
|
||||
return config.SNPFirmwareSignerConfig{}, err
|
||||
@ -174,11 +174,11 @@ func convertFromTfFirmwareCfg(tfFirmwareCfg azureSnpFirmwareSignerConfig) (confi
|
||||
}
|
||||
|
||||
// convertToTfMeasurements converts the constellation measurements to the terraform struct.
|
||||
func convertToTfMeasurements(m measurements.M) map[string]measurement {
|
||||
tfMeasurements := map[string]measurement{}
|
||||
func convertToTfMeasurements(m measurements.M) map[string]measurementAttribute {
|
||||
tfMeasurements := map[string]measurementAttribute{}
|
||||
for key, value := range m {
|
||||
keyStr := strconv.FormatUint(uint64(key), 10)
|
||||
tfMeasurements[keyStr] = measurement{
|
||||
tfMeasurements[keyStr] = measurementAttribute{
|
||||
Expected: hex.EncodeToString(value.Expected),
|
||||
WarnOnly: bool(value.ValidationOpt),
|
||||
}
|
||||
@ -186,32 +186,6 @@ func convertToTfMeasurements(m measurements.M) map[string]measurement {
|
||||
return tfMeasurements
|
||||
}
|
||||
|
||||
type extraMicroservices struct {
|
||||
CSIDriver bool `tfsdk:"csi_driver"`
|
||||
}
|
||||
|
||||
type measurement struct {
|
||||
Expected string `tfsdk:"expected"`
|
||||
WarnOnly bool `tfsdk:"warn_only"`
|
||||
}
|
||||
|
||||
type attestation 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 azureSnpFirmwareSignerConfig `tfsdk:"azure_firmware_signer_config"`
|
||||
Variant string `tfsdk:"variant"`
|
||||
Measurements map[string]measurement `tfsdk:"measurements"`
|
||||
}
|
||||
|
||||
type azureSnpFirmwareSignerConfig struct {
|
||||
AcceptedKeyDigests []string `tfsdk:"accepted_key_digests"`
|
||||
EnforcementPolicy string `tfsdk:"enforcement_policy"`
|
||||
MAAURL string `tfsdk:"maa_url"`
|
||||
}
|
||||
|
||||
func newVersion(v uint8) config.AttestationVersion {
|
||||
return config.AttestationVersion{
|
||||
Value: v,
|
||||
|
@ -18,18 +18,18 @@ import (
|
||||
)
|
||||
|
||||
func TestParseAttestationConfig(t *testing.T) {
|
||||
testAttestation := attestation{
|
||||
testAttestation := attestationAttribute{
|
||||
BootloaderVersion: 1,
|
||||
TEEVersion: 2,
|
||||
SNPVersion: 3,
|
||||
MicrocodeVersion: 4,
|
||||
AMDRootKey: "\"-----BEGIN CERTIFICATE-----\\nMIIGYzCCBBKgAwIBAgIDAQAAMEYGCSqGSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAIC\\nBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAICBQCiAwIBMKMDAgEBMHsxFDAS\\nBgNVBAsMC0VuZ2luZWVyaW5nMQswCQYDVQQGEwJVUzEUMBIGA1UEBwwLU2FudGEg\\nQ2xhcmExCzAJBgNVBAgMAkNBMR8wHQYDVQQKDBZBZHZhbmNlZCBNaWNybyBEZXZp\\nY2VzMRIwEAYDVQQDDAlBUkstTWlsYW4wHhcNMjAxMDIyMTcyMzA1WhcNNDUxMDIy\\nMTcyMzA1WjB7MRQwEgYDVQQLDAtFbmdpbmVlcmluZzELMAkGA1UEBhMCVVMxFDAS\\nBgNVBAcMC1NhbnRhIENsYXJhMQswCQYDVQQIDAJDQTEfMB0GA1UECgwWQWR2YW5j\\nZWQgTWljcm8gRGV2aWNlczESMBAGA1UEAwwJQVJLLU1pbGFuMIICIjANBgkqhkiG\\n9w0BAQEFAAOCAg8AMIICCgKCAgEA0Ld52RJOdeiJlqK2JdsVmD7FktuotWwX1fNg\\nW41XY9Xz1HEhSUmhLz9Cu9DHRlvgJSNxbeYYsnJfvyjx1MfU0V5tkKiU1EesNFta\\n1kTA0szNisdYc9isqk7mXT5+KfGRbfc4V/9zRIcE8jlHN61S1ju8X93+6dxDUrG2\\nSzxqJ4BhqyYmUDruPXJSX4vUc01P7j98MpqOS95rORdGHeI52Naz5m2B+O+vjsC0\\n60d37jY9LFeuOP4Meri8qgfi2S5kKqg/aF6aPtuAZQVR7u3KFYXP59XmJgtcog05\\ngmI0T/OitLhuzVvpZcLph0odh/1IPXqx3+MnjD97A7fXpqGd/y8KxX7jksTEzAOg\\nbKAeam3lm+3yKIcTYMlsRMXPcjNbIvmsBykD//xSniusuHBkgnlENEWx1UcbQQrs\\n+gVDkuVPhsnzIRNgYvM48Y+7LGiJYnrmE8xcrexekBxrva2V9TJQqnN3Q53kt5vi\\nQi3+gCfmkwC0F0tirIZbLkXPrPwzZ0M9eNxhIySb2npJfgnqz55I0u33wh4r0ZNQ\\neTGfw03MBUtyuzGesGkcw+loqMaq1qR4tjGbPYxCvpCq7+OgpCCoMNit2uLo9M18\\nfHz10lOMT8nWAUvRZFzteXCm+7PHdYPlmQwUw3LvenJ/ILXoQPHfbkH0CyPfhl1j\\nWhJFZasCAwEAAaN+MHwwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSFrBrRQ/fI\\nrFXUxR1BSKvVeErUUzAPBgNVHRMBAf8EBTADAQH/MDoGA1UdHwQzMDEwL6AtoCuG\\nKWh0dHBzOi8va2RzaW50Zi5hbWQuY29tL3ZjZWsvdjEvTWlsYW4vY3JsMEYGCSqG\\nSIb3DQEBCjA5oA8wDQYJYIZIAWUDBAICBQChHDAaBgkqhkiG9w0BAQgwDQYJYIZI\\nAWUDBAICBQCiAwIBMKMDAgEBA4ICAQC6m0kDp6zv4Ojfgy+zleehsx6ol0ocgVel\\nETobpx+EuCsqVFRPK1jZ1sp/lyd9+0fQ0r66n7kagRk4Ca39g66WGTJMeJdqYriw\\nSTjjDCKVPSesWXYPVAyDhmP5n2v+BYipZWhpvqpaiO+EGK5IBP+578QeW/sSokrK\\ndHaLAxG2LhZxj9aF73fqC7OAJZ5aPonw4RE299FVarh1Tx2eT3wSgkDgutCTB1Yq\\nzT5DuwvAe+co2CIVIzMDamYuSFjPN0BCgojl7V+bTou7dMsqIu/TW/rPCX9/EUcp\\nKGKqPQ3P+N9r1hjEFY1plBg93t53OOo49GNI+V1zvXPLI6xIFVsh+mto2RtgEX/e\\npmMKTNN6psW88qg7c1hTWtN6MbRuQ0vm+O+/2tKBF2h8THb94OvvHHoFDpbCELlq\\nHnIYhxy0YKXGyaW1NjfULxrrmxVW4wcn5E8GddmvNa6yYm8scJagEi13mhGu4Jqh\\n3QU3sf8iUSUr09xQDwHtOQUVIqx4maBZPBtSMf+qUDtjXSSq8lfWcd8bLr9mdsUn\\nJZJ0+tuPMKmBnSH860llKk+VpVQsgqbzDIvOLvD6W1Umq25boxCYJ+TuBoa4s+HH\\nCViAvgT9kf/rBq1d+ivj6skkHxuzcxbk1xv6ZGxrteJxVH7KlX7YRdZ6eARKwLe4\\nAFZEAwoKCQ==\\n-----END CERTIFICATE-----\\n\"",
|
||||
AzureSNPFirmwareSignerConfig: azureSnpFirmwareSignerConfig{
|
||||
AzureSNPFirmwareSignerConfig: azureSnpFirmwareSignerConfigAttribute{
|
||||
AcceptedKeyDigests: []string{"0356215882a825279a85b300b0b742931d113bf7e32dde2e50ffde7ec743ca491ecdd7f336dc28a6e0b2bb57af7a44a3"},
|
||||
EnforcementPolicy: "equal",
|
||||
MAAURL: "https://example.com",
|
||||
},
|
||||
Measurements: map[string]measurement{
|
||||
Measurements: map[string]measurementAttribute{
|
||||
"1": {Expected: "48656c6c6f", WarnOnly: false}, // "Hello" in hex
|
||||
"2": {Expected: "776f726c64", WarnOnly: true}, // "world" in hex
|
||||
},
|
||||
@ -65,7 +65,7 @@ func TestParseAttestationConfig(t *testing.T) {
|
||||
|
||||
// Test error scenarios
|
||||
t.Run("invalid_measurement_index", func(t *testing.T) {
|
||||
testAttestation.Measurements = map[string]measurement{"invalid": {Expected: "data"}}
|
||||
testAttestation.Measurements = map[string]measurementAttribute{"invalid": {Expected: "data"}}
|
||||
attestationVariant := variant.AzureSEVSNP{}
|
||||
|
||||
_, err := convertFromTfAttestationCfg(testAttestation, attestationVariant)
|
||||
|
@ -10,7 +10,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/edgelesssys/constellation/v2/internal/api/versionsapi"
|
||||
"github.com/edgelesssys/constellation/v2/internal/attestation/variant"
|
||||
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
|
||||
"github.com/edgelesssys/constellation/v2/internal/imagefetcher"
|
||||
@ -54,11 +56,11 @@ type imageFetcher interface {
|
||||
// ImageDataSourceModel defines the image data source's data model.
|
||||
type ImageDataSourceModel struct {
|
||||
AttestationVariant types.String `tfsdk:"attestation_variant"`
|
||||
ImageVersion types.String `tfsdk:"image_version"`
|
||||
Version types.String `tfsdk:"version"`
|
||||
CSP types.String `tfsdk:"csp"`
|
||||
MarketplaceImage types.Bool `tfsdk:"marketplace_image"`
|
||||
Region types.String `tfsdk:"region"`
|
||||
Reference types.String `tfsdk:"reference"`
|
||||
Image types.Object `tfsdk:"image"`
|
||||
}
|
||||
|
||||
// Metadata returns the metadata for the image data source.
|
||||
@ -72,13 +74,14 @@ func (d *ImageDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
|
||||
Description: "The data source to resolve the CSP-specific OS image reference for a given version and attestation variant.",
|
||||
MarkdownDescription: "Data source to resolve the CSP-specific OS image reference for a given version and attestation variant.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"attestation_variant": newAttestationVariantAttribute(attributeInput),
|
||||
"image_version": schema.StringAttribute{
|
||||
// Input Attributes
|
||||
"attestation_variant": newAttestationVariantAttributeSchema(attributeInput),
|
||||
"version": schema.StringAttribute{
|
||||
Description: "Version of the Constellation OS image to use. (e.g. `v2.13.0`). If not set, the provider version is used.",
|
||||
MarkdownDescription: "Version of the Constellation OS image to use. (e.g. `v2.13.0`). If not set, the provider version value is used.",
|
||||
Optional: true,
|
||||
},
|
||||
"csp": newCSPAttribute(),
|
||||
"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.",
|
||||
@ -91,11 +94,8 @@ func (d *ImageDataSource) Schema(_ context.Context, _ datasource.SchemaRequest,
|
||||
"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.",
|
||||
Optional: true,
|
||||
},
|
||||
"reference": schema.StringAttribute{
|
||||
Description: "CSP-specific reference to the image.",
|
||||
MarkdownDescription: "CSP-specific reference to the image.",
|
||||
Computed: true,
|
||||
},
|
||||
// Output Attributes
|
||||
"image": newImageAttributeSchema(attributeOutput),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -162,17 +162,51 @@ func (d *ImageDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
||||
fmt.Sprintf("When parsing the Attestation Variant (%s), an error occurred: %s", data.AttestationVariant.ValueString(), err),
|
||||
)
|
||||
}
|
||||
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
imageVersion := data.ImageVersion.ValueString()
|
||||
// lock-step with the provider
|
||||
imageVersion := data.Version.ValueString()
|
||||
if imageVersion == "" {
|
||||
tflog.Info(ctx, fmt.Sprintf("No image version specified, using provider version %s", d.version))
|
||||
imageVersion = d.version // Use provider version as default.
|
||||
}
|
||||
|
||||
// determine semver from version string
|
||||
var imageSemver string
|
||||
var apiCompatibleVer versionsapi.Version
|
||||
if strings.HasPrefix(imageVersion, "v") {
|
||||
// If the version is a release version, it should look like vX.Y.Z
|
||||
imageSemver = imageVersion
|
||||
apiCompatibleVer, err = versionsapi.NewVersion(
|
||||
versionsapi.ReleaseRef,
|
||||
"stable",
|
||||
imageVersion,
|
||||
versionsapi.VersionKindImage,
|
||||
)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("version"),
|
||||
"Invalid Version",
|
||||
fmt.Sprintf("When parsing the version (%s), an error occurred: %s", imageVersion, err),
|
||||
)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// otherwise, it should be a versionsapi short path
|
||||
apiCompatibleVer, err = versionsapi.NewVersionFromShortPath(imageVersion, versionsapi.VersionKindImage)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddAttributeError(
|
||||
path.Root("version"),
|
||||
"Invalid Version",
|
||||
fmt.Sprintf("When parsing the version (%s), an error occurred: %s", imageVersion, err),
|
||||
)
|
||||
return
|
||||
}
|
||||
imageSemver = apiCompatibleVer.Version()
|
||||
}
|
||||
|
||||
// Retrieve Image Reference
|
||||
imageRef, err := d.imageFetcher.FetchReference(ctx, csp, attestationVariant,
|
||||
imageVersion, data.Region.ValueString(), data.MarketplaceImage.ValueBool())
|
||||
@ -192,7 +226,13 @@ func (d *ImageDataSource) Read(ctx context.Context, req datasource.ReadRequest,
|
||||
}
|
||||
|
||||
// Save data into Terraform state
|
||||
data.Reference = types.StringValue(imageRef)
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
diags := resp.State.SetAttribute(ctx, path.Root("image"), imageAttribute{
|
||||
Reference: imageRef,
|
||||
Version: imageSemver,
|
||||
ShortPath: apiCompatibleVer.ShortPath(),
|
||||
})
|
||||
resp.Diagnostics.Append(diags...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
bazelPreCheck := func() { bazelSetTerraformBinaryPath(t) }
|
||||
|
||||
testCases := map[string]resource.TestCase{
|
||||
"no image_version succeeds": {
|
||||
"no version succeeds": {
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactoriesWithVersion("v2.13.0"),
|
||||
PreCheck: bazelPreCheck,
|
||||
Steps: []resource.TestStep{
|
||||
@ -30,7 +30,11 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
region = "eu-west-1"
|
||||
}
|
||||
`,
|
||||
Check: resource.TestCheckResourceAttrSet("data.constellation_image.test", "reference"),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttrSet("data.constellation_image.test", "image.reference"),
|
||||
resource.TestCheckResourceAttrSet("data.constellation_image.test", "image.version"),
|
||||
resource.TestCheckResourceAttrSet("data.constellation_image.test", "image.short_path"),
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -42,13 +46,13 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
{
|
||||
Config: testingConfig + `
|
||||
data "constellation_image" "test" {
|
||||
image_version = "v2.13.0"
|
||||
version = "v2.13.0"
|
||||
attestation_variant = "aws-sev-snp"
|
||||
csp = "aws"
|
||||
region = "eu-west-1"
|
||||
}
|
||||
`,
|
||||
Check: resource.TestCheckResourceAttr("data.constellation_image.test", "reference", "ami-04f8d522b113b73bf"), // should be immutable
|
||||
Check: resource.TestCheckResourceAttr("data.constellation_image.test", "image.reference", "ami-04f8d522b113b73bf"), // should be immutable
|
||||
|
||||
},
|
||||
},
|
||||
@ -61,7 +65,7 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
{
|
||||
Config: testingConfig + `
|
||||
data "constellation_image" "test" {
|
||||
image_version = "v2.13.0"
|
||||
version = "v2.13.0"
|
||||
attestation_variant = "aws-sev-snp"
|
||||
csp = "aws"
|
||||
}
|
||||
@ -78,12 +82,12 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
{
|
||||
Config: testingConfig + `
|
||||
data "constellation_image" "test" {
|
||||
image_version = "v2.13.0"
|
||||
version = "v2.13.0"
|
||||
attestation_variant = "azure-sev-snp"
|
||||
csp = "azure"
|
||||
}
|
||||
`,
|
||||
Check: resource.TestCheckResourceAttr("data.constellation_image.test", "reference", "/communityGalleries/ConstellationCVM-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/2.13.0"), // should be immutable
|
||||
Check: resource.TestCheckResourceAttr("data.constellation_image.test", "image.reference", "/communityGalleries/ConstellationCVM-b3782fa0-0df7-4f2f-963e-fc7fc42663df/images/constellation/versions/2.13.0"), // should be immutable
|
||||
|
||||
},
|
||||
},
|
||||
@ -96,13 +100,13 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
{
|
||||
Config: testingConfig + `
|
||||
data "constellation_image" "test" {
|
||||
image_version = "v2.13.0"
|
||||
version = "v2.13.0"
|
||||
attestation_variant = "azure-sev-snp"
|
||||
csp = "azure"
|
||||
marketplace_image = true
|
||||
}
|
||||
`,
|
||||
Check: resource.TestCheckResourceAttr("data.constellation_image.test", "reference", "constellation-marketplace-image://Azure?offer=constellation&publisher=edgelesssystems&sku=constellation&version=2.13.0"), // should be immutable
|
||||
Check: resource.TestCheckResourceAttr("data.constellation_image.test", "image.reference", "constellation-marketplace-image://Azure?offer=constellation&publisher=edgelesssystems&sku=constellation&version=2.13.0"), // should be immutable
|
||||
|
||||
},
|
||||
},
|
||||
@ -115,12 +119,12 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
{
|
||||
Config: testingConfig + `
|
||||
data "constellation_image" "test" {
|
||||
image_version = "v2.13.0"
|
||||
version = "v2.13.0"
|
||||
attestation_variant = "gcp-sev-es"
|
||||
csp = "gcp"
|
||||
}
|
||||
`,
|
||||
Check: resource.TestCheckResourceAttr("data.constellation_image.test", "reference", "projects/constellation-images/global/images/v2-13-0-gcp-sev-es-stable"), // should be immutable,
|
||||
Check: resource.TestCheckResourceAttr("data.constellation_image.test", "image.reference", "projects/constellation-images/global/images/v2-13-0-gcp-sev-es-stable"), // should be immutable,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -132,7 +136,7 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
{
|
||||
Config: testingConfig + `
|
||||
data "constellation_image" "test" {
|
||||
image_version = "v2.13.0"
|
||||
version = "v2.13.0"
|
||||
attestation_variant = "unknown"
|
||||
csp = "azure"
|
||||
}
|
||||
@ -149,7 +153,7 @@ func TestAccImageDataSource(t *testing.T) {
|
||||
{
|
||||
Config: testingConfig + `
|
||||
data "constellation_image" "test" {
|
||||
image_version = "v2.13.0"
|
||||
version = "v2.13.0"
|
||||
attestation_variant = "azure-sev-snp"
|
||||
csp = "unknown"
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ const (
|
||||
|
||||
type attributeType bool
|
||||
|
||||
func newAttestationVariantAttribute(t attributeType) schema.Attribute {
|
||||
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`)",
|
||||
@ -39,7 +39,7 @@ func newAttestationVariantAttribute(t attributeType) schema.Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
func newCSPAttribute() schema.Attribute {
|
||||
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" +
|
||||
@ -51,7 +51,7 @@ func newCSPAttribute() schema.Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
func newMeasurementsAttribute(t attributeType) schema.Attribute {
|
||||
func newMeasurementsAttributeSchema(t attributeType) schema.Attribute {
|
||||
isInput := bool(t)
|
||||
return schema.MapNestedAttribute{
|
||||
Computed: !isInput,
|
||||
@ -71,7 +71,13 @@ func newMeasurementsAttribute(t attributeType) schema.Attribute {
|
||||
}
|
||||
}
|
||||
|
||||
func newAttestationConfigAttribute(t attributeType) schema.Attribute {
|
||||
// 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 {
|
||||
@ -83,7 +89,7 @@ func newAttestationConfigAttribute(t attributeType) schema.Attribute {
|
||||
MarkdownDescription: "Attestation comprises the measurements and SEV-SNP specific parameters." + additionalDescription,
|
||||
Description: "Attestation comprises the measurements and SEV-SNP specific parameters." + additionalDescription,
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"variant": newAttestationVariantAttribute(t), // duplicated for convenience in cluster resource
|
||||
"variant": newAttestationVariantAttributeSchema(t), // duplicated for convenience in cluster resource
|
||||
"bootloader_version": schema.Int64Attribute{
|
||||
Computed: !isInput,
|
||||
Required: isInput,
|
||||
@ -123,7 +129,66 @@ func newAttestationConfigAttribute(t attributeType) schema.Attribute {
|
||||
Computed: !isInput,
|
||||
Required: isInput,
|
||||
},
|
||||
"measurements": newMeasurementsAttribute(t),
|
||||
"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"`
|
||||
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"`
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// imageAttribute is the image attribute's data model.
|
||||
type imageAttribute struct {
|
||||
Reference string `tfsdk:"reference"`
|
||||
Version string `tfsdk:"version"`
|
||||
ShortPath string `tfsdk:"short_path"`
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user