diff --git a/dev-docs/workflows/terraform-provider.md b/dev-docs/workflows/terraform-provider.md index a100b4593..812bd68c6 100644 --- a/dev-docs/workflows/terraform-provider.md +++ b/dev-docs/workflows/terraform-provider.md @@ -43,7 +43,12 @@ TF_CLI_CONFIG_FILE=config.tfrc terraform apply Terraform acceptance tests can be run hermetically through Bazel (recommended): ```bash -bazel test //terraform-provider-constellation/internal/provider:provider_acc_test +bazel test --test_tag_filters=integration //terraform-provider-constellation/internal/provider:provider_acc_test ``` The tests can also be run through Go, but the `TF_ACC` environment variable needs to be set to `1`, and the host's Terraform binary is used, which may produce inaccurate test results. + +```bash +cd terraform-provider-constellation +TF_ACC=1 go test -v ./... +``` diff --git a/internal/attestation/idkeydigest/idkeydigest.go b/internal/attestation/idkeydigest/idkeydigest.go index 5bb3e714c..45b5a54c0 100644 --- a/internal/attestation/idkeydigest/idkeydigest.go +++ b/internal/attestation/idkeydigest/idkeydigest.go @@ -159,9 +159,11 @@ func (d *List) UnmarshalYAML(unmarshal func(any) error) error { } encodedDigests = append(encodedDigests, unmarshalledString) } - if err := d.unmarshal(encodedDigests); err != nil { + res, err := UnmarshalHexString(encodedDigests) + if err != nil { return fmt.Errorf("unmarshalling yaml: %w", err) } + *d = res return nil } @@ -188,23 +190,26 @@ func (d *List) UnmarshalJSON(b []byte) error { } encodedDigests = []string{unmarshalledString} } - if err := d.unmarshal(encodedDigests); err != nil { + res, err := UnmarshalHexString(encodedDigests) + if err != nil { return fmt.Errorf("unmarshalling json: %w", err) } + *d = res return nil } -// unmarshal is a helper function for unmarshalling encodedIDKeyDigests into IDKeyDigests. -func (d *List) unmarshal(encodedDigests encodedList) error { - for _, encodedDigest := range encodedDigests { +// UnmarshalHexString unmarshals a list of hex encoded ID key digest strings. +func UnmarshalHexString(encodedDigests []string) (List, error) { + res := make(List, len(encodedDigests)) + for idx, encodedDigest := range encodedDigests { if len(encodedDigest) != encodedDigestLength { - return fmt.Errorf("invalid digest length: %d", len(encodedDigest)) + return nil, fmt.Errorf("invalid digest length: %d", len(encodedDigest)) } digest, err := hex.DecodeString(encodedDigest) if err != nil { - return fmt.Errorf("decoding digest: %w", err) + return nil, fmt.Errorf("decoding digest: %w", err) } - *d = append(*d, digest) + res[idx] = digest } - return nil + return res, nil } diff --git a/rfc/014-terraform-provider.md b/rfc/014-terraform-provider.md index b4b7074aa..1984c48c4 100644 --- a/rfc/014-terraform-provider.md +++ b/rfc/014-terraform-provider.md @@ -31,10 +31,10 @@ resource "constellation_cluster" "foo" { name = "baz" image = data.constellation_image.ref # or provide manually crafted values kubernetes_version = "v1.27.6" - constellation_microservice_version = "lockstep" # or pinned to a specific version debug = false init_endpoint = "10.10.10.10" # should use public ip of LB resource, ideally also provisioned through TF kubernetes_api_endpoint = "10.10.10.10" # should use public ip of LB resource, ideally also provisioned through TF + constellation_microservice_version = "v2.13.0" # optional value, set to provider version by default. extra_microservices = { csi_driver = true # + more diff --git a/terraform-provider-constellation/docs/data-sources/attestation.md b/terraform-provider-constellation/docs/data-sources/attestation.md index fb11df2ac..377adbfdf 100644 --- a/terraform-provider-constellation/docs/data-sources/attestation.md +++ b/terraform-provider-constellation/docs/data-sources/attestation.md @@ -40,9 +40,7 @@ See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview ### Read-Only -- `attestation` (Attributes) Only relevant for SEV-SNP. (see [below for nested schema](#nestedatt--attestation)) -- `id` (String) The ID of the data source -- `measurements` (Attributes Map) (see [below for nested schema](#nestedatt--measurements)) +- `attestation` (Attributes) Attestation comprises the measurements and SEV-SNP specific parameters. (see [below for nested schema](#nestedatt--attestation)) ### Nested Schema for `attestation` @@ -52,9 +50,15 @@ Read-Only: - `amd_root_key` (String) - `azure_firmware_signer_config` (Attributes) (see [below for nested schema](#nestedatt--attestation--azure_firmware_signer_config)) - `bootloader_version` (Number) +- `measurements` (Attributes Map) (see [below for nested schema](#nestedatt--attestation--measurements)) - `microcode_version` (Number) - `snp_version` (Number) - `tee_version` (Number) +- `variant` (String) Attestation variant the image should work with. Can be one of: + * `aws-sev-snp` + * `aws-nitro-tpm` + * `azure-sev-snp` + * `gcp-sev-es` ### Nested Schema for `attestation.azure_firmware_signer_config` @@ -66,9 +70,8 @@ Read-Only: - `maa_url` (String) - - -### Nested Schema for `measurements` + +### Nested Schema for `attestation.measurements` Read-Only: diff --git a/terraform-provider-constellation/docs/data-sources/image.md b/terraform-provider-constellation/docs/data-sources/image.md index c7f5a99bb..f8cf8dabe 100644 --- a/terraform-provider-constellation/docs/data-sources/image.md +++ b/terraform-provider-constellation/docs/data-sources/image.md @@ -42,5 +42,4 @@ The Constellation OS image must be [replicated to the region](https://docs.edgel ### Read-Only -- `id` (String) The ID of this resource. - `reference` (String) CSP-specific reference to the image. diff --git a/terraform-provider-constellation/docs/resources/cluster.md b/terraform-provider-constellation/docs/resources/cluster.md new file mode 100644 index 000000000..23cf75dd8 --- /dev/null +++ b/terraform-provider-constellation/docs/resources/cluster.md @@ -0,0 +1,87 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "constellation_cluster Resource - constellation" +subcategory: "" +description: |- + Resource for a Constellation cluster. +--- + +# constellation_cluster (Resource) + +Resource for a Constellation cluster. + + + + +## Schema + +### Required + +- `attestation` (Attributes) Attestation comprises the measurements and SEV-SNP specific parameters. (see [below for nested schema](#nestedatt--attestation)) +- `init_secret` (String) The init secret to use for the cluster. +- `master_secret` (String) The master secret to use for the cluster. +- `uid` (String) The UID of the cluster. + +### Optional + +- `constellation_microservices_version` (String) The Constellation microservices version to use for the cluster. +- `extra_microservices` (Attributes) Extra microservice settings. (see [below for nested schema](#nestedatt--extra_microservices)) +- `image` (String) The Constellation OS image to use in the CSP specific reference format. Use the `constellation_image` data source to find the correct image for your CSP. +- `init_endpoint` (String) The endpoint to use for cluster initialization. This is the endpoint of the node running the bootstrapper. +- `kubernetes_api_endpoint` (String) The endpoint to use for the Kubernetes API. +- `kubernetes_version` (String) The Kubernetes version to use for the cluster. When not set, the latest default version ("v1.27.7") will be used. The supported versions are [v1.26.10 v1.27.7 v1.28.3]. +- `name` (String) Name used in the cluster's named resources / cluster name. + +### Read-Only + +- `cluster_id` (String) The cluster ID of the cluster. +- `kubeconfig` (String) The kubeconfig of the cluster. +- `owner_id` (String) The owner ID of the cluster. + + +### Nested Schema for `attestation` + +Required: + +- `amd_root_key` (String) +- `bootloader_version` (Number) +- `measurements` (Attributes Map) (see [below for nested schema](#nestedatt--attestation--measurements)) +- `microcode_version` (Number) +- `snp_version` (Number) +- `tee_version` (Number) +- `variant` (String) Attestation variant the image should work with. Can be one of: + * `aws-sev-snp` + * `aws-nitro-tpm` + * `azure-sev-snp` + * `gcp-sev-es` + +Optional: + +- `azure_firmware_signer_config` (Attributes) (see [below for nested schema](#nestedatt--attestation--azure_firmware_signer_config)) + + +### Nested Schema for `attestation.measurements` + +Required: + +- `expected` (String) +- `warn_only` (Boolean) + + + +### Nested Schema for `attestation.azure_firmware_signer_config` + +Optional: + +- `accepted_key_digests` (List of String) +- `enforcement_policy` (String) +- `maa_url` (String) + + + + +### Nested Schema for `extra_microservices` + +Optional: + +- `csi_driver` (Boolean) Enable the CSI driver microservice. diff --git a/terraform-provider-constellation/docs/resources/example.md b/terraform-provider-constellation/docs/resources/example.md deleted file mode 100644 index 66831e655..000000000 --- a/terraform-provider-constellation/docs/resources/example.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "constellation_example Resource - constellation" -subcategory: "" -description: |- - Example resource ---- - -# constellation_example (Resource) - -Example resource - - - - -## Schema - -### Optional - -- `configurable_attribute` (String) Example configurable attribute -- `defaulted` (String) Example configurable attribute with default value - -### Read-Only - -- `id` (String) Example identifier diff --git a/terraform-provider-constellation/go.mod b/terraform-provider-constellation/go.mod index 93c3686eb..57ddd11ae 100644 --- a/terraform-provider-constellation/go.mod +++ b/terraform-provider-constellation/go.mod @@ -14,9 +14,20 @@ require ( github.com/hashicorp/terraform-plugin-go v0.19.1 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-testing v1.5.1 + github.com/stretchr/testify v1.8.4 ) require ( + cloud.google.com/go/compute v1.23.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c // indirect + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/applicationinsights/armapplicationinsights v1.1.1 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.1.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.0.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 // indirect github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect github.com/agext/levenshtein v1.2.2 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect @@ -33,6 +44,7 @@ require ( github.com/aws/aws-sdk-go-v2/internal/ini v1.3.35 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.26 // indirect github.com/aws/aws-sdk-go-v2/service/cloudfront v1.26.8 // indirect + github.com/aws/aws-sdk-go-v2/service/ec2 v1.102.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.29 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.28 // indirect @@ -45,9 +57,13 @@ require ( github.com/blang/semver v3.5.1+incompatible // indirect github.com/cloudflare/circl v1.3.3 // indirect github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/edgelesssys/go-azguestattestation v0.0.0-20230707101700-a683be600fcf // indirect + github.com/edgelesssys/go-tdx-qpl v0.0.0-20230530085549-fd2878a4dead // indirect github.com/fatih/color v1.15.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/go-chi/chi v4.1.2+incompatible // indirect + github.com/go-jose/go-jose/v3 v3.0.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/analysis v0.21.4 // indirect @@ -63,11 +79,24 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.14.1 // indirect + github.com/gofrs/uuid v4.2.0+incompatible // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/google/certificate-transparency-go v1.1.4 // indirect + github.com/google/go-attestation v0.5.0 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-containerregistry v0.15.2 // indirect + github.com/google/go-sev-guest v0.9.3 // indirect + github.com/google/go-tdx-guest v0.2.3-0.20231011100059-4cf02bed9d33 // indirect github.com/google/go-tpm v0.9.0 // indirect + github.com/google/go-tpm-tools v0.4.2 // indirect + github.com/google/go-tspi v0.3.0 // indirect + github.com/google/logger v1.1.1 // indirect + github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.4.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect @@ -92,13 +121,14 @@ require ( github.com/jedisct1/go-minisign v0.0.0-20211028175153-1c139d1cc84b // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/kr/pretty v0.3.0 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/microsoft/ApplicationInsights-Go v0.4.4 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -109,7 +139,10 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/pborman/uuid v1.2.1 // indirect + github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/sassoftware/relic v7.2.1+incompatible // indirect github.com/schollz/progressbar/v3 v3.13.1 // indirect @@ -126,8 +159,10 @@ require ( github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810 // indirect github.com/zclconf/go-cty v1.14.1 // indirect go.mongodb.org/mongo-driver v1.11.3 // indirect + go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel v1.14.0 // indirect go.opentelemetry.io/otel/trace v1.14.0 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -136,14 +171,22 @@ require ( golang.org/x/exp v0.0.0-20230809150735-7b3493d9a819 // indirect golang.org/x/mod v0.13.0 // indirect golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/term v0.13.0 // indirect golang.org/x/text v0.14.0 // indirect + google.golang.org/api v0.148.0 // indirect google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a // indirect google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apimachinery v0.28.2 // indirect + k8s.io/klog/v2 v2.100.1 // indirect + k8s.io/kubernetes v1.27.5 // indirect + k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect ) diff --git a/terraform-provider-constellation/go.sum b/terraform-provider-constellation/go.sum index 35f496c5b..ade75dbe6 100644 --- a/terraform-provider-constellation/go.sum +++ b/terraform-provider-constellation/go.sum @@ -17,12 +17,18 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.110.8 h1:tyNdfIxjzaWctIiLYOTalaLKZ17SI44SKFW26QbOhME= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -35,11 +41,39 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c h1:5eeuG0BHx1+DHeT3AP+ISKZ2ht1UjGhm581ljqYpVeQ= +code.cloudfoundry.org/clock v0.0.0-20180518195852-02e53af36e6c/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230618160516-e936619f9f18 h1:rd389Q26LMy03gG4anandGFC2LW/xvjga5GezeeaxQk= github.com/AdamKorcz/go-fuzz-headers-1 v0.0.0-20230618160516-e936619f9f18/go.mod h1:fgJuSBrJP5qZtKqaMJE0hmhS2tmRH+44IkfZvjtaf1M= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1 h1:SEy2xmstIphdPwNBUi7uhvjyjhVKISfwjfOJmuy7kg4= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.1/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 h1:sXr+ck84g/ZlZUOZiNELInmMgOsuGwdjjVkEIde0OtY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/applicationinsights/armapplicationinsights v1.1.1 h1:hBrFatNIiVAwDb5GzMLjpkQ6l2/waFSvBWMBWZRH8WI= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/applicationinsights/armapplicationinsights v1.1.1/go.mod h1:uxknLoFj+nBXpfGngz0B4ciNur04Y0EX4AREpy2GIvk= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.1.0 h1:Sg/D8VuUQ+bw+FOYJF+xRKcwizCOP13HL0Se8pWNBzE= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.1.0/go.mod h1:Kyqzdqq0XDoCm+o9aZ25wZBmBUBzPBzPAj1R5rYsT6I= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2 h1:mLY+pNLjCUeKhgnAJWAKhEUQM+RJQo2H1fuGSw1Ky1E= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal v1.1.2/go.mod h1:FbdwsQ2EzwvXxOPcMFYO8ogEc9uMMIj3YkmCdXdAFmk= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.0.0 h1:pqCyNi/Paz03SbWRmGlb5WBzK14aOXVuSJuOTWzOM5M= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.0.0/go.mod h1:bCUhQ1sbQHAG4nm1SqWwLlnKnRVT2e6Lu0cij7OzliM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1 h1:7CBQ+Ei8SP2c6ydQTGCCrS35bDxgTMfoP2miAwK++OU= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.1.1/go.mod h1:c/wcGeGx5FUPbM/JltUYHZcKmigwyVLJlDq+4HdtXaw= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= +github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= +github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= @@ -84,6 +118,8 @@ github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.26 h1:wscW+pnn3J1OYnanMnza5ZVYXLX github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.26/go.mod h1:MtYiox5gvyB+OyP0Mr0Sm/yzbEAIPL9eijj/ouHAPw0= github.com/aws/aws-sdk-go-v2/service/cloudfront v1.26.8 h1:loRDtQ0vT0+JCB0hQBCfv95tttEzJ1rqSaTDy5cpy0A= github.com/aws/aws-sdk-go-v2/service/cloudfront v1.26.8/go.mod h1:YTd4wGn2beCF9wkSTpEcupk79zDFYJk2Ca76B8YyvJg= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.102.0 h1:P4dyjm49F2kKws0FpouBC6fjVImACXKt752+CWa01lM= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.102.0/go.mod h1:tIctCeX9IbzsUTKHt53SVEcgyfxV2ElxJeEB+QUbc4M= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.29 h1:zZSLP3v3riMOP14H7b4XP0uyfREDQOYv2cqIrvTXDNQ= @@ -134,6 +170,12 @@ github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnG github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/edgelesssys/go-azguestattestation v0.0.0-20230707101700-a683be600fcf h1:1iKB7b+i7svWC0aKXwggi+kHf0K57g8r9hN4VOpJYYg= +github.com/edgelesssys/go-azguestattestation v0.0.0-20230707101700-a683be600fcf/go.mod h1:T8Rv3qrCpUJZbKq49OA9tcC1ZbRkGtDxiafsj++LYIE= +github.com/edgelesssys/go-tdx-qpl v0.0.0-20230530085549-fd2878a4dead h1:Q2TI34V/NCLGQQkdc0/KmPx/7ix9YnGDUQDT+gqvDw0= +github.com/edgelesssys/go-tdx-qpl v0.0.0-20230530085549-fd2878a4dead/go.mod h1:IC72qyykUIWl0ZmSk53L4xbLCFDBEGZVaujUmPQOEyw= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -151,6 +193,7 @@ github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52/go.mod h1:yIquW8 github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/go-chi/chi v4.1.2+incompatible h1:fGFk2Gmi/YKXk0OmGfBh0WgmN3XB8lVnEyNz34tQRec= @@ -164,6 +207,9 @@ github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= +github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -244,6 +290,11 @@ github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/V github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -278,6 +329,11 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg= +github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= +github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= +github.com/google/go-attestation v0.5.0 h1:jXtAWT2sw2Yu8mYU0BC7FDidR+ngxFPSE+pl6IUu3/0= +github.com/google/go-attestation v0.5.0/go.mod h1:0Tik9y3rzV649Jcr7evbljQHQAsIlJucyqQjYDBqktU= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -286,6 +342,7 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -293,10 +350,20 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.15.2 h1:MMkSh+tjSdnmJZO7ljvEqV1DjfekB6VUEAZgy3a+TQE= github.com/google/go-containerregistry v0.15.2/go.mod h1:wWK+LnOv4jXMM23IT/F1wdYftGWGr47Is8CG+pmHK1Q= +github.com/google/go-sev-guest v0.9.3 h1:GOJ+EipURdeWFl/YYdgcCxyPeMgQUWlI056iFkBD8UU= +github.com/google/go-sev-guest v0.9.3/go.mod h1:hc1R4R6f8+NcJwITs0L90fYWTsBpd1Ix+Gur15sqHDs= +github.com/google/go-tdx-guest v0.2.3-0.20231011100059-4cf02bed9d33 h1:lRlUusuieEuqljjihCXb+Mr73VNitOYPJYWXzJKtBWs= +github.com/google/go-tdx-guest v0.2.3-0.20231011100059-4cf02bed9d33/go.mod h1:84ut3oago/BqPXD4ppiGXdkZNW3WFPkcyAO4my2hXdY= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= +github.com/google/go-tpm-tools v0.4.2 h1:iyaCPKt2N5Rd0yz0G8ANa022SgCNZkMpp+db6QELtvI= +github.com/google/go-tpm-tools v0.4.2/go.mod h1:fGUDZu4tw3V4hUVuFHmiYgRd0c58/IXivn9v3Ea/ck4= +github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus= +github.com/google/go-tspi v0.3.0/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ= +github.com/google/logger v1.1.1/go.mod h1:BkeJZ+1FhQ+/d087r4dzojEg1u2ZX+ZqG1jTUrLM+zQ= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -311,12 +378,19 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0 h1:2cz5kSrxzMYHiWOBbKj8itQm+nRykkB8aMv4ThcHYHA= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.0/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= @@ -380,6 +454,7 @@ github.com/honeycombio/libhoney-go v1.16.0 h1:kPpqoz6vbOzgp7jC6SR7SkNj7rua7rgxvz github.com/honeycombio/libhoney-go v1.16.0/go.mod h1:izP4fbREuZ3vqC4HlCAmPrcPT9gxyxejRjGtCYpmBn0= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM= github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -416,8 +491,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -428,6 +503,8 @@ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf h1:ndns1qx/5dL43g16EQkPV/i8+b3l5bYQwLeoSBe7tS8= github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf/go.mod h1:aGkAgvWY/IUcVFfuly53REpfv5edu25oij+qHRFaraA= +github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= @@ -449,6 +526,8 @@ github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWV github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/microsoft/ApplicationInsights-Go v0.4.4 h1:G4+H9WNs6ygSCe6sUyxRc2U81TI5Es90b2t/MwX5KqY= +github.com/microsoft/ApplicationInsights-Go v0.4.4/go.mod h1:fKRUseBqkw6bDiXTs3ESTiU/4YTIHsQS4W3fP2ieF4U= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= @@ -469,13 +548,20 @@ github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw= +github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -498,7 +584,6 @@ github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -548,6 +633,7 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/tedsuo/ifrit v0.0.0-20180802180643-bea94bb476cc/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0= github.com/theupdateframework/go-tuf v0.5.2 h1:habfDzTmpbzBLIFGWa2ZpVhYvFBoK0C1onC3a4zuPRA= github.com/theupdateframework/go-tuf v0.5.2/go.mod h1:SyMV5kg5n4uEclsyxXJZI2UxPFJNDc4Y+r7wv+MlvTA= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= @@ -564,6 +650,8 @@ github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IU github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810 h1:X6ps8XHfpQjw8dUStzlMi2ybiKQ2Fmdw7UM+TinwvyM= +github.com/vtolstov/go-ioctl v0.0.0-20151206205506-6be9cced4810/go.mod h1:dF0BBJ2YrV1+2eAIyEI+KeSidgA6HqoIP1u5XTlMq/o= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -592,6 +680,8 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM= go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY= @@ -609,6 +699,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -661,6 +752,7 @@ golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -687,6 +779,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -708,6 +801,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -722,8 +817,11 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -763,7 +861,9 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -880,6 +980,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.148.0 h1:HBq4TZlN4/1pNcu0geJZ/Q50vIwIXT532UIMYoo0vOs= +google.golang.org/api v0.148.0/go.mod h1:8/TBgwaKjfqTdacOJrOv2+2Q6fBDU1uHKK06oGSkxzU= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -924,6 +1026,10 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a h1:a2MQQVoTo96JC9PMGtGBymLp7+/RzpFc2yX/9WfFg1c= google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -966,10 +1072,13 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -987,6 +1096,14 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= +k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= +k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= +k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/kubernetes v1.27.5 h1:qnkrNAPz2jm/k+oWBNOJ6q+kCQ7OXkO8v3WWU9jumwo= +k8s.io/kubernetes v1.27.5/go.mod h1:MbYZxAacYS6HjZ6VJuvKaKTilbzp0B0atzW3J8TFBEo= +k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= +k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/terraform-provider-constellation/internal/provider/BUILD.bazel b/terraform-provider-constellation/internal/provider/BUILD.bazel index 53e8bba32..42e04708a 100644 --- a/terraform-provider-constellation/internal/provider/BUILD.bazel +++ b/terraform-provider-constellation/internal/provider/BUILD.bazel @@ -5,33 +5,37 @@ go_library( name = "provider", srcs = [ "attestation_data_source.go", - "example_resource.go", + "cluster_resource.go", + "convert.go", "image_data_source.go", "provider.go", + "shared_attributes.go", ], importpath = "github.com/edgelesssys/constellation/v2/terraform-provider-constellation/internal/provider", visibility = ["//terraform-provider-constellation:__subpackages__"], deps = [ "//internal/api/attestationconfigapi", + "//internal/attestation/choose", + "//internal/attestation/idkeydigest", "//internal/attestation/measurements", "//internal/attestation/variant", "//internal/cloud/cloudprovider", "//internal/config", "//internal/imagefetcher", "//internal/sigstore", + "//internal/versions", "//terraform-provider-constellation/internal/data", "@com_github_hashicorp_terraform_plugin_framework//datasource", "@com_github_hashicorp_terraform_plugin_framework//datasource/schema", + "@com_github_hashicorp_terraform_plugin_framework//diag", "@com_github_hashicorp_terraform_plugin_framework//path", "@com_github_hashicorp_terraform_plugin_framework//provider", "@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/stringdefault", - "@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", "@com_github_hashicorp_terraform_plugin_framework_validators//stringvalidator", "@com_github_hashicorp_terraform_plugin_log//tflog", ], @@ -41,14 +45,22 @@ go_test( name = "provider_test", srcs = [ "attestation_data_source_test.go", + "cluster_resource_test.go", + "convert_test.go", "image_data_source_test.go", "provider_test.go", ], embed = [":provider"], deps = [ + "//internal/attestation/idkeydigest", + "//internal/attestation/measurements", + "//internal/attestation/variant", + "//internal/config", "@com_github_hashicorp_terraform_plugin_framework//providerserver", "@com_github_hashicorp_terraform_plugin_go//tfprotov6", "@com_github_hashicorp_terraform_plugin_testing//helper/resource", + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", "@io_bazel_rules_go//go/runfiles:go_default_library", ], ) diff --git a/terraform-provider-constellation/internal/provider/attestation_data_source.go b/terraform-provider-constellation/internal/provider/attestation_data_source.go index eeced12f9..6260edba1 100644 --- a/terraform-provider-constellation/internal/provider/attestation_data_source.go +++ b/terraform-provider-constellation/internal/provider/attestation_data_source.go @@ -8,23 +8,18 @@ package provider import ( "context" - "encoding/hex" "errors" "fmt" "net/http" - "strconv" "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" - "github.com/edgelesssys/constellation/v2/internal/config" "github.com/edgelesssys/constellation/v2/internal/sigstore" - "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" ) @@ -50,8 +45,6 @@ type AttestationDataSourceModel struct { AttestationVariant types.String `tfsdk:"attestation_variant"` ImageVersion types.String `tfsdk:"image_version"` MaaURL types.String `tfsdk:"maa_url"` - ID types.String `tfsdk:"id"` - Measurements types.Map `tfsdk:"measurements"` Attestation types.Object `tfsdk:"attestation"` } @@ -79,27 +72,8 @@ func (d *AttestationDataSource) Schema(_ context.Context, _ datasource.SchemaReq MarkdownDescription: "The data source to fetch measurements from a configured cloud provider and image.", Attributes: map[string]schema.Attribute{ - "csp": schema.StringAttribute{ - Description: "CSP (Cloud Service Provider) to use. (e.g. `azure`)", - MarkdownDescription: "CSP (Cloud Service Provider) to use. (e.g. `azure`)\n" + - "See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports.", - Required: true, - Validators: []validator.String{ - stringvalidator.OneOf("aws", "azure", "gcp"), - }, - }, - "attestation_variant": schema.StringAttribute{ - Description: "Attestation variant the image should work with. (e.g. `azure-sev-snp`)", - MarkdownDescription: "Attestation variant the image should work with. Can be one of:\n" + - " * `aws-sev-snp`\n" + - " * `aws-nitro-tpm`\n" + - " * `azure-sev-snp`\n" + - " * `gcp-sev-es`\n", - Required: true, - Validators: []validator.String{ - stringvalidator.OneOf("aws-sev-snp", "aws-nitro-tpm", "azure-sev-snp", "gcp-sev-es"), - }, - }, + "csp": newCSPAttribute(), + "attestation_variant": newAttestationVariantAttribute(attributeInput), "image_version": schema.StringAttribute{ MarkdownDescription: "The image version to use", Required: true, @@ -108,60 +82,7 @@ func (d *AttestationDataSource) Schema(_ context.Context, _ datasource.SchemaReq MarkdownDescription: "For Azure only, the URL of the Microsoft Azure Attestation service", Optional: true, }, - "id": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "The ID of the data source", - }, - "measurements": schema.MapNestedAttribute{ - Computed: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "expected": schema.StringAttribute{ - Computed: true, - }, - "warn_only": schema.BoolAttribute{ - Computed: true, - }, - }, - }, - }, - "attestation": schema.SingleNestedAttribute{ - Computed: true, - MarkdownDescription: "Only relevant for SEV-SNP.", - Description: "The values provide sensible defaults. See the docs for advanced usage.", // TODO(elchead): AB#3568 - Attributes: map[string]schema.Attribute{ - "bootloader_version": schema.Int64Attribute{ - Computed: true, - }, - "tee_version": schema.Int64Attribute{ - Computed: true, - }, - "snp_version": schema.Int64Attribute{ - Computed: true, - }, - "microcode_version": schema.Int64Attribute{ - Computed: true, - }, - "azure_firmware_signer_config": schema.SingleNestedAttribute{ - Computed: true, - Attributes: map[string]schema.Attribute{ - "accepted_key_digests": schema.ListAttribute{ - Computed: true, - ElementType: types.StringType, - }, - "enforcement_policy": schema.StringAttribute{ - Computed: true, - }, - "maa_url": schema.StringAttribute{ - Computed: true, - }, - }, - }, - "amd_root_key": schema.StringAttribute{ - Computed: true, - }, - }, - }, + "attestation": newAttestationConfigAttribute(attributeOutput), }, } } @@ -191,27 +112,23 @@ func (d *AttestationDataSource) Read(ctx context.Context, req datasource.ReadReq resp.Diagnostics.AddAttributeError( path.Root("attestation_variant"), "Invalid Attestation Variant", - fmt.Sprintf("Invalid attestation variant: %s", data.CSP.ValueString()), + fmt.Sprintf("Invalid attestation variant: %s", data.AttestationVariant.ValueString()), ) return } + + snpVersions := attestationconfigapi.SEVSNPVersionAPI{} if attestationVariant.Equal(variant.AzureSEVSNP{}) || attestationVariant.Equal(variant.AWSSEVSNP{}) { - snpVersions, err := d.fetcher.FetchSEVSNPVersionLatest(ctx, attestationVariant) + snpVersions, err = d.fetcher.FetchSEVSNPVersionLatest(ctx, attestationVariant) if err != nil { resp.Diagnostics.AddError("Fetching SNP Version numbers", err.Error()) return } - tfSnpAttestation, err := convertSNPAttestationTfStateCompatible(attestationVariant, snpVersions) - if err != nil { - resp.Diagnostics.AddError("Converting SNP attestation", err.Error()) - } - diags := resp.State.SetAttribute(ctx, path.Root("attestation"), tfSnpAttestation) - resp.Diagnostics.Append(diags...) - if resp.Diagnostics.HasError() { - return - } } - + tfAttestation, err := convertToTfAttestation(attestationVariant, snpVersions) + if err != nil { + resp.Diagnostics.AddError("Converting SNP attestation", err.Error()) + } verifyFetcher := measurements.NewVerifyFetcher(sigstore.NewCosignVerifier, d.rekor, d.client) fetchedMeasurements, err := verifyFetcher.FetchAndVerifyMeasurements(ctx, data.ImageVersion.ValueString(), csp, attestationVariant, false) @@ -224,83 +141,12 @@ func (d *AttestationDataSource) Read(ctx context.Context, req datasource.ReadReq return } } - tfMeasurements := convertMeasurementsTfStateCompatible(fetchedMeasurements) - diags := resp.State.SetAttribute(ctx, path.Root("measurements"), tfMeasurements) + tfAttestation.Measurements = convertToTfMeasurements(fetchedMeasurements) + + diags := resp.State.SetAttribute(ctx, path.Root("attestation"), tfAttestation) resp.Diagnostics.Append(diags...) if resp.Diagnostics.HasError() { return } tflog.Trace(ctx, "read constellation attestation data source") } - -func convertSNPAttestationTfStateCompatible(attestationVariant variant.Variant, - snpVersions attestationconfigapi.SEVSNPVersionAPI, -) (tfSnpAttestation sevSnpAttestation, err error) { - var cert config.Certificate - switch attestationVariant.(type) { - case variant.AWSSEVSNP: - cert = config.DefaultForAWSSEVSNP().AMDRootKey - case variant.AzureSEVSNP: - cert = config.DefaultForAzureSEVSNP().AMDRootKey - } - certBytes, err := cert.MarshalJSON() - if err != nil { - return tfSnpAttestation, err - } - tfSnpAttestation = sevSnpAttestation{ - BootloaderVersion: snpVersions.Bootloader, - TEEVersion: snpVersions.TEE, - SNPVersion: snpVersions.SNP, - MicrocodeVersion: snpVersions.Microcode, - AMDRootKey: string(certBytes), - } - if attestationVariant.Equal(variant.AzureSEVSNP{}) { - firmwareCfg := config.DefaultForAzureSEVSNP().FirmwareSignerConfig - keyDigestAny, err := firmwareCfg.AcceptedKeyDigests.MarshalYAML() - if err != nil { - return tfSnpAttestation, err - } - keyDigest, ok := keyDigestAny.([]string) - if !ok { - return tfSnpAttestation, errors.New("reading Accepted Key Digests: could not convert to []string") - } - tfSnpAttestation.AzureSNPFirmwareSignerConfig = azureSnpFirmwareSignerConfig{ - AcceptedKeyDigests: keyDigest, - EnforcementPolicy: firmwareCfg.EnforcementPolicy.String(), - MAAURL: firmwareCfg.MAAURL, - } - } - return tfSnpAttestation, nil -} - -func convertMeasurementsTfStateCompatible(m measurements.M) map[string]measurement { - tfMeasurements := map[string]measurement{} - for key, value := range m { - keyStr := strconv.FormatUint(uint64(key), 10) - tfMeasurements[keyStr] = measurement{ - Expected: hex.EncodeToString(value.Expected[:]), - WarnOnly: bool(value.ValidationOpt), - } - } - return tfMeasurements -} - -type measurement struct { - Expected string `tfsdk:"expected"` - WarnOnly bool `tfsdk:"warn_only"` -} - -type sevSnpAttestation 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"` -} - -type azureSnpFirmwareSignerConfig struct { - AcceptedKeyDigests []string `tfsdk:"accepted_key_digests"` - EnforcementPolicy string `tfsdk:"enforcement_policy"` - MAAURL string `tfsdk:"maa_url"` -} diff --git a/terraform-provider-constellation/internal/provider/attestation_data_source_test.go b/terraform-provider-constellation/internal/provider/attestation_data_source_test.go index 21341c0ed..52e6d2c30 100644 --- a/terraform-provider-constellation/internal/provider/attestation_data_source_test.go +++ b/terraform-provider-constellation/internal/provider/attestation_data_source_test.go @@ -30,14 +30,16 @@ func TestAccAttestationSource(t *testing.T) { } `, 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", "measurements.0.expected", "7b068c0c3ac29afe264134536b9be26f1d4ccd575b88d3c3ceabf36ac99c0278"), - resource.TestCheckResourceAttr("data.constellation_attestation.test", "measurements.0.warn_only", "true"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.0.expected", "7b068c0c3ac29afe264134536b9be26f1d4ccd575b88d3c3ceabf36ac99c0278"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.0.warn_only", "true"), ), }, }, @@ -55,6 +57,8 @@ func TestAccAttestationSource(t *testing.T) { } `, Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.variant", "azure-sev-snp"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.bootloader_version", "3"), resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.microcode_version", "115"), resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.snp_version", "8"), @@ -65,8 +69,8 @@ func TestAccAttestationSource(t *testing.T) { 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", "measurements.1.expected", "3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969"), - resource.TestCheckResourceAttr("data.constellation_attestation.test", "measurements.1.warn_only", "true"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.1.expected", "3d458cfe55cc03ea1f443f1562beec8df51c75e14a9fcf9a7234a13f198e7969"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.1.warn_only", "true"), ), }, }, @@ -84,8 +88,11 @@ func TestAccAttestationSource(t *testing.T) { } `, Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("data.constellation_attestation.test", "measurements.1.expected", "745f2fb4235e4647aa0ad5ace781cd929eb68c28870e7dd5d1a1535854325e56"), - resource.TestCheckResourceAttr("data.constellation_attestation.test", "measurements.1.warn_only", "true"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.variant", "gcp-sev-es"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.bootloader_version", "0"), // since this is not supported on GCP, we expect 0 + + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.1.expected", "745f2fb4235e4647aa0ad5ace781cd929eb68c28870e7dd5d1a1535854325e56"), + resource.TestCheckResourceAttr("data.constellation_attestation.test", "attestation.measurements.1.warn_only", "true"), ), }, }, diff --git a/terraform-provider-constellation/internal/provider/cluster_resource.go b/terraform-provider-constellation/internal/provider/cluster_resource.go new file mode 100644 index 000000000..dbf391692 --- /dev/null +++ b/terraform-provider-constellation/internal/provider/cluster_resource.go @@ -0,0 +1,303 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package provider + +import ( + "context" + "fmt" + + "github.com/edgelesssys/constellation/v2/internal/attestation/choose" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" + "github.com/edgelesssys/constellation/v2/internal/versions" + "github.com/hashicorp/terraform-plugin-framework/diag" + "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/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure provider defined types fully satisfy framework interfaces. +var ( + _ resource.Resource = &ClusterResource{} + _ resource.ResourceWithImportState = &ClusterResource{} +) + +// NewClusterResource creates a new cluster resource. +func NewClusterResource() resource.Resource { + return &ClusterResource{} +} + +// ClusterResource defines the resource implementation. +type ClusterResource struct{} + +// ClusterResourceModel describes the resource data model. +type ClusterResourceModel struct { + UID types.String `tfsdk:"uid"` + Name types.String `tfsdk:"name"` + Image types.String `tfsdk:"image"` + KubernetesVersion types.String `tfsdk:"kubernetes_version"` + InitEndpoint types.String `tfsdk:"init_endpoint"` + KubernetesAPIEndpoint types.String `tfsdk:"kubernetes_api_endpoint"` + MicroserviceVersion types.String `tfsdk:"constellation_microservices_version"` + ExtraMicroservices types.Object `tfsdk:"extra_microservices"` + MasterSecret types.String `tfsdk:"master_secret"` + InitSecret types.String `tfsdk:"init_secret"` + Attestation types.Object `tfsdk:"attestation"` + OwnerID types.String `tfsdk:"owner_id"` + ClusterID types.String `tfsdk:"cluster_id"` + Kubeconfig types.String `tfsdk:"kubeconfig"` + // NetworkConfig types.Object `tfsdk:"network_config"` // TODO(elchead): do when clear what is needed +} + +// Metadata returns the metadata of the resource. +func (r *ClusterResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_cluster" +} + +// Schema returns the schema of the resource. +func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Resource for a Constellation cluster.", + Description: "Resource for a Constellation cluster.", + + Attributes: map[string]schema.Attribute{ + "uid": schema.StringAttribute{ + MarkdownDescription: "The UID of the cluster.", + Description: "The UID of the cluster.", + Required: true, + }, + "name": schema.StringAttribute{ + MarkdownDescription: "Name used in the cluster's named resources / cluster name.", + Description: "Name used in the cluster's named resources / cluster name.", + Optional: true, // TODO(elchead): use "constell" as default + }, + "image": schema.StringAttribute{ + MarkdownDescription: "The Constellation OS image to use in the CSP specific reference format. Use the `constellation_image` data source to find the correct image for your CSP.", + Description: "The Constellation OS image to use in the CSP specific reference format. Use the `constellation_image` data source to find the correct image for your CSP. When not set, the latest default version will be used.", + Optional: true, + }, + "kubernetes_version": schema.StringAttribute{ + MarkdownDescription: fmt.Sprintf("The Kubernetes version to use for the cluster. When not set, the latest default version (%q) will be used. The supported versions are %s.", versions.Default, versions.SupportedK8sVersions()), + Description: fmt.Sprintf("The Kubernetes version to use for the cluster. When not set, the latest default version (%q) will be used. The supported versions are %s.", versions.Default, versions.SupportedK8sVersions()), + Optional: true, + }, + "constellation_microservices_version": schema.StringAttribute{ + MarkdownDescription: "The Constellation microservices version to use for the cluster.", + Description: "The Constellation microservices version to use for the cluster. When not set, the latest default version will be used.", + Optional: true, + }, + "init_endpoint": schema.StringAttribute{ + MarkdownDescription: "The endpoint to use for cluster initialization. This is the endpoint of the node running the bootstrapper.", + Description: "The endpoint to use for cluster initialization.", + Optional: true, + }, + "kubernetes_api_endpoint": schema.StringAttribute{ + MarkdownDescription: "The endpoint to use for the Kubernetes API.", + Description: "The endpoint to use for the Kubernetes API. When not set, the default endpoint will be used.", + Optional: true, + }, + "extra_microservices": schema.SingleNestedAttribute{ + MarkdownDescription: "Extra microservice settings.", + Description: "Extra microservice settings.", + Optional: true, + Attributes: map[string]schema.Attribute{ + "csi_driver": schema.BoolAttribute{ + Optional: true, + MarkdownDescription: "Enable the CSI driver microservice.", + Description: "Enable the CSI driver microservice.", + }, + }, + }, + "master_secret": schema.StringAttribute{ + MarkdownDescription: "The master secret to use for the cluster.", + Description: "The master secret to use for the cluster.", + Required: true, + }, + "init_secret": schema.StringAttribute{ + MarkdownDescription: "The init secret to use for the cluster.", + Description: "The init secret to use for the cluster.", + Required: true, + }, + "attestation": newAttestationConfigAttribute(attributeInput), + "owner_id": schema.StringAttribute{ + MarkdownDescription: "The owner ID of the cluster.", + Description: "The owner ID of the cluster.", + Computed: true, + }, + "cluster_id": schema.StringAttribute{ + MarkdownDescription: "The cluster ID of the cluster.", + Description: "The cluster ID of the cluster.", + Computed: true, + }, + "kubeconfig": schema.StringAttribute{ + MarkdownDescription: "The kubeconfig of the cluster.", + Description: "The kubeconfig of the cluster.", + Computed: true, + }, + }, + } +} + +// Configure configures the resource. +func (r *ClusterResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + // client, ok := req.ProviderData.(*http.Client) + + // if !ok { + // resp.Diagnostics.AddError( + // "Unexpected Resource Configure Type", + // fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + // ) + + // return + //} +} + +// Create is called when the resource is created. +func (r *ClusterResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data ClusterResourceModel + // Read Terraform plan data into the model + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + var tfAttestation attestation + diags := data.Attestation.As(ctx, &tfAttestation, basetypes.ObjectAsOptions{}) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + attestationVariant, err := variant.FromString(tfAttestation.Variant) + if err != nil { + resp.Diagnostics.AddAttributeError( + path.Root("attestation_variant"), + "Invalid Attestation Variant", + fmt.Sprintf("Invalid attestation variant: %s", tfAttestation.Variant)) + return + } + attestationCfg, err := convertFromTfAttestationCfg(tfAttestation, attestationVariant) + if err != nil { + resp.Diagnostics.AddError("Parsing attestation config", err.Error()) + return + } + + var extraMicroservices extraMicroservices + diags = data.ExtraMicroservices.As(ctx, &extraMicroservices, basetypes.ObjectAsOptions{}) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + // TODO(elchead): implement in follow up PR + data.OwnerID = types.StringValue("owner_id") + data.ClusterID = types.StringValue("cluster_id") + data.Kubeconfig = types.StringValue("kubeconfig") + // applier := constellation.NewApplier(log) + _, err = choose.Validator(attestationCfg, &tfLogger{dg: &resp.Diagnostics}) + if err != nil { + resp.Diagnostics.AddError("Choosing validator", err.Error()) + return + } + + // Write logs using the tflog package + // Documentation: https://terraform.io/plugin/log + tflog.Trace(ctx, "created a resource") + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +// Read is called when the resource is read or refreshed. +func (r *ClusterResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data ClusterResourceModel + + // Read Terraform prior state data into the model + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // If applicable, this is a great opportunity to initialize any necessary + // provider client data and make a call using it. + // httpResp, err := r.client.Do(httpReq) + // if err != nil { + // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read example, got error: %s", err)) + // return + // } + + // Save updated data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +// Update is called when the resource is updated. +func (r *ClusterResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data ClusterResourceModel + + // Read Terraform plan data into the model + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // If applicable, this is a great opportunity to initialize any necessary + // provider client data and make a call using it. + // httpResp, err := r.client.Do(httpReq) + // if err != nil { + // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update example, got error: %s", err)) + // return + // } + + // Save updated data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +// Delete is called when the resource is destroyed. +func (r *ClusterResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data ClusterResourceModel + + // Read Terraform prior state data into the model + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // If applicable, this is a great opportunity to initialize any necessary + // provider client data and make a call using it. + // httpResp, err := r.client.Do(httpReq) + // if err != nil { + // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete example, got error: %s", err)) + // return + // } +} + +// ImportState imports to the resource. +func (r *ClusterResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +type tfLogger struct { + dg *diag.Diagnostics +} + +func (l *tfLogger) Infof(format string, args ...any) { + tflog.Info(context.Background(), fmt.Sprintf(format, args...)) +} + +func (l *tfLogger) Warnf(format string, args ...any) { + l.dg.AddWarning(fmt.Sprintf(format, args...), "") +} diff --git a/terraform-provider-constellation/internal/provider/cluster_resource_test.go b/terraform-provider-constellation/internal/provider/cluster_resource_test.go new file mode 100644 index 000000000..03db18962 --- /dev/null +++ b/terraform-provider-constellation/internal/provider/cluster_resource_test.go @@ -0,0 +1,56 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package provider + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccClusterResource(t *testing.T) { + // Set the path to the Terraform binary for acceptance testing when running under Bazel. + bazelPreCheck := func() { bazelSetTerraformBinaryPath(t) } + + testCases := map[string]resource.TestCase{ + "azure sev-snp success": { + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + PreCheck: bazelPreCheck, + Steps: []resource.TestStep{ + { + Config: testingConfig + ` + data "constellation_attestation" "att" { + csp = "azure" + attestation_variant = "azure-sev-snp" + image_version = "v2.13.0" + } + + resource "constellation_cluster" "test" { + uid = "test" + master_secret = "secret" + init_secret = "secret" + attestation = data.constellation_attestation.att.attestation + extra_microservices = { + csi_driver = true + } + } + `, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("constellation_cluster.test", "attestation.bootloader_version", "3"), + // TODO(elchead): check output in follow up PR + ), + }, + }, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + resource.Test(t, tc) + }) + } +} diff --git a/terraform-provider-constellation/internal/provider/convert.go b/terraform-provider-constellation/internal/provider/convert.go new file mode 100644 index 000000000..c375c1347 --- /dev/null +++ b/terraform-provider-constellation/internal/provider/convert.go @@ -0,0 +1,196 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package provider + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "strconv" + + "github.com/edgelesssys/constellation/v2/internal/api/attestationconfigapi" + "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" + "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" + "github.com/edgelesssys/constellation/v2/internal/config" +) + +// naming schema: +// convertFromTf : convert a terraform struct to a constellation struct +// convertToTf : convert a constellation struct to a terraform struct +// terraform struct: used to parse the terraform state +// 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) { + c11nMeasurements := make(measurements.M) + for strIdx, v := range tfAttestation.Measurements { + idx, err := strconv.ParseUint(strIdx, 10, 32) + if err != nil { + return nil, err + } + expectedBt, err := hex.DecodeString(v.Expected) + if err != nil { + return nil, err + } + var valOption measurements.MeasurementValidationOption + switch v.WarnOnly { + case true: + valOption = measurements.WarnOnly + case false: + valOption = measurements.Enforce + } + c11nMeasurements[uint32(idx)] = measurements.Measurement{ + Expected: expectedBt, + ValidationOpt: valOption, + } + } + + var attestationConfig config.AttestationCfg + switch attestationVariant { + case variant.AzureSEVSNP{}: + firmwareCfg, err := convertFromTfFirmwareCfg(tfAttestation.AzureSNPFirmwareSignerConfig) + if err != nil { + return nil, fmt.Errorf("converting firmware signer config: %w", err) + } + var rootKey config.Certificate + if err := json.Unmarshal([]byte(tfAttestation.AMDRootKey), &rootKey); err != nil { + return nil, fmt.Errorf("unmarshalling root key: %w", err) + } + + attestationConfig = &config.AzureSEVSNP{ + Measurements: c11nMeasurements, + BootloaderVersion: newVersion(tfAttestation.BootloaderVersion), + TEEVersion: newVersion(tfAttestation.TEEVersion), + SNPVersion: newVersion(tfAttestation.SNPVersion), + MicrocodeVersion: newVersion(tfAttestation.MicrocodeVersion), + FirmwareSignerConfig: firmwareCfg, + AMDRootKey: rootKey, + } + } + return attestationConfig, nil +} + +// convertToTfAttestationCfg converts the constellation attestation config to the related terraform structs. +func convertToTfAttestation(attestationVariant variant.Variant, + snpVersions attestationconfigapi.SEVSNPVersionAPI, +) (tfAttestation attestation, err error) { + // set fields that apply to all variants + tfAttestation = attestation{ + Variant: attestationVariant.String(), + BootloaderVersion: snpVersions.Bootloader, + TEEVersion: snpVersions.TEE, + SNPVersion: snpVersions.SNP, + MicrocodeVersion: snpVersions.Microcode, + } + switch attestationVariant.(type) { + case variant.AWSSEVSNP: + certStr, err := certAsString(config.DefaultForAWSSEVSNP().AMDRootKey) + if err != nil { + return tfAttestation, err + } + tfAttestation.AMDRootKey = certStr + + case variant.AzureSEVSNP: + certStr, err := certAsString(config.DefaultForAWSSEVSNP().AMDRootKey) + if err != nil { + return tfAttestation, err + } + tfAttestation.AMDRootKey = certStr + + firmwareCfg := config.DefaultForAzureSEVSNP().FirmwareSignerConfig + tfFirmwareCfg, err := convertToTfFirmwareCfg(firmwareCfg) + if err != nil { + return tfAttestation, err + } + tfAttestation.AzureSNPFirmwareSignerConfig = tfFirmwareCfg + } + return tfAttestation, nil +} + +func certAsString(cert config.Certificate) (string, error) { + certBytes, err := cert.MarshalJSON() + if err != nil { + return "", err + } + return string(certBytes), nil +} + +// convertToTfFirmwareCfg converts the constellation firmware config to the terraform struct. +func convertToTfFirmwareCfg(firmwareCfg config.SNPFirmwareSignerConfig) (azureSnpFirmwareSignerConfig, error) { + keyDigestAny, err := firmwareCfg.AcceptedKeyDigests.MarshalYAML() + if err != nil { + return azureSnpFirmwareSignerConfig{}, err + } + keyDigest, ok := keyDigestAny.([]string) + if !ok { + return azureSnpFirmwareSignerConfig{}, fmt.Errorf("reading Accepted Key Digests: could not convert %T to []string", keyDigestAny) + } + return azureSnpFirmwareSignerConfig{ + AcceptedKeyDigests: keyDigest, + EnforcementPolicy: firmwareCfg.EnforcementPolicy.String(), + MAAURL: firmwareCfg.MAAURL, + }, nil +} + +// convertFromTfFirmwareCfg converts the terraform struct to a constellation firmware config. +func convertFromTfFirmwareCfg(tfFirmwareCfg azureSnpFirmwareSignerConfig) (config.SNPFirmwareSignerConfig, error) { + keyDigests, err := idkeydigest.UnmarshalHexString(tfFirmwareCfg.AcceptedKeyDigests) + if err != nil { + return config.SNPFirmwareSignerConfig{}, err + } + return config.SNPFirmwareSignerConfig{ + AcceptedKeyDigests: keyDigests, + EnforcementPolicy: idkeydigest.EnforcePolicyFromString(tfFirmwareCfg.EnforcementPolicy), + MAAURL: tfFirmwareCfg.MAAURL, + }, nil +} + +// convertToTfMeasurements converts the constellation measurements to the terraform struct. +func convertToTfMeasurements(m measurements.M) map[string]measurement { + tfMeasurements := map[string]measurement{} + for key, value := range m { + keyStr := strconv.FormatUint(uint64(key), 10) + tfMeasurements[keyStr] = measurement{ + Expected: hex.EncodeToString(value.Expected), + WarnOnly: bool(value.ValidationOpt), + } + } + 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, + } +} diff --git a/terraform-provider-constellation/internal/provider/convert_test.go b/terraform-provider-constellation/internal/provider/convert_test.go new file mode 100644 index 000000000..1a3a9d00a --- /dev/null +++ b/terraform-provider-constellation/internal/provider/convert_test.go @@ -0,0 +1,84 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package provider + +import ( + "testing" + + "github.com/edgelesssys/constellation/v2/internal/attestation/idkeydigest" + "github.com/edgelesssys/constellation/v2/internal/attestation/measurements" + "github.com/edgelesssys/constellation/v2/internal/attestation/variant" + "github.com/edgelesssys/constellation/v2/internal/config" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestParseAttestationConfig(t *testing.T) { + testAttestation := attestation{ + 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{ + AcceptedKeyDigests: []string{"0356215882a825279a85b300b0b742931d113bf7e32dde2e50ffde7ec743ca491ecdd7f336dc28a6e0b2bb57af7a44a3"}, + EnforcementPolicy: "equal", + MAAURL: "https://example.com", + }, + Measurements: map[string]measurement{ + "1": {Expected: "48656c6c6f", WarnOnly: false}, // "Hello" in hex + "2": {Expected: "776f726c64", WarnOnly: true}, // "world" in hex + }, + } + t.Run("Azure SEV-SNP success", func(t *testing.T) { + attestationVariant := variant.AzureSEVSNP{} + + cfg, err := convertFromTfAttestationCfg(testAttestation, attestationVariant) + require.NoError(t, err) + require.NotNil(t, cfg) + + azureCfg, ok := cfg.(*config.AzureSEVSNP) + require.True(t, ok) + + require.Equal(t, "ARK-Milan", azureCfg.AMDRootKey.Issuer.CommonName) + + require.Equal(t, uint8(1), azureCfg.BootloaderVersion.Value) + require.Equal(t, uint8(2), azureCfg.TEEVersion.Value) + require.Equal(t, uint8(3), azureCfg.SNPVersion.Value) + require.Equal(t, uint8(4), azureCfg.MicrocodeVersion.Value) + + require.Equal(t, []byte("Hello"), azureCfg.Measurements[1].Expected) + require.Equal(t, measurements.Enforce, azureCfg.Measurements[1].ValidationOpt) + + require.Equal(t, []byte("world"), azureCfg.Measurements[2].Expected) + require.Equal(t, measurements.WarnOnly, azureCfg.Measurements[2].ValidationOpt) + + require.Equal(t, "https://example.com", azureCfg.FirmwareSignerConfig.MAAURL) + require.Equal(t, idkeydigest.Equal, azureCfg.FirmwareSignerConfig.EnforcementPolicy) + + assert.Len(t, azureCfg.FirmwareSignerConfig.AcceptedKeyDigests, 1) + }) + + // Test error scenarios + t.Run("invalid_measurement_index", func(t *testing.T) { + testAttestation.Measurements = map[string]measurement{"invalid": {Expected: "data"}} + attestationVariant := variant.AzureSEVSNP{} + + _, err := convertFromTfAttestationCfg(testAttestation, attestationVariant) + assert.Error(t, err) + }) + + t.Run("invalid_amd_root_key", func(t *testing.T) { + invalidAttestation := testAttestation + invalidAttestation.AMDRootKey = "not valid json" + + attestationVariant := variant.AzureSEVSNP{} + + _, err := convertFromTfAttestationCfg(invalidAttestation, attestationVariant) + assert.Error(t, err) + }) +} diff --git a/terraform-provider-constellation/internal/provider/example_resource.go b/terraform-provider-constellation/internal/provider/example_resource.go deleted file mode 100644 index ac69897c4..000000000 --- a/terraform-provider-constellation/internal/provider/example_resource.go +++ /dev/null @@ -1,201 +0,0 @@ -/* -Copyright (c) Edgeless Systems GmbH - -SPDX-License-Identifier: AGPL-3.0-only -*/ - -package provider - -import ( - "context" - "fmt" - "net/http" - - "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/stringdefault" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" - "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-log/tflog" -) - -// Ensure provider defined types fully satisfy framework interfaces. -var ( - _ resource.Resource = &ExampleResource{} - _ resource.ResourceWithImportState = &ExampleResource{} -) - -// NewExampleResource creates a new examplary resource. -func NewExampleResource() resource.Resource { - return &ExampleResource{} -} - -// ExampleResource defines the resource implementation. -type ExampleResource struct { - client *http.Client -} - -// ExampleResourceModel describes the resource data model. -type ExampleResourceModel struct { - ConfigurableAttribute types.String `tfsdk:"configurable_attribute"` - Defaulted types.String `tfsdk:"defaulted"` - ID types.String `tfsdk:"id"` -} - -// Metadata returns the metadata of the resource. -func (r *ExampleResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_example" -} - -// Schema returns the schema of the resource. -func (r *ExampleResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { - resp.Schema = schema.Schema{ - // This description is used by the documentation generator and the language server. - MarkdownDescription: "Example resource", - - Attributes: map[string]schema.Attribute{ - "configurable_attribute": schema.StringAttribute{ - MarkdownDescription: "Example configurable attribute", - Optional: true, - }, - "defaulted": schema.StringAttribute{ - MarkdownDescription: "Example configurable attribute with default value", - Optional: true, - Computed: true, - Default: stringdefault.StaticString("example value when not configured"), - }, - "id": schema.StringAttribute{ - Computed: true, - MarkdownDescription: "Example identifier", - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, - }, - }, - } -} - -// Configure configures the resource. -func (r *ExampleResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { - // Prevent panic if the provider has not been configured. - if req.ProviderData == nil { - return - } - - client, ok := req.ProviderData.(*http.Client) - - if !ok { - resp.Diagnostics.AddError( - "Unexpected Resource Configure Type", - fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), - ) - - return - } - - r.client = client -} - -// Create is called when the resource is created. -func (r *ExampleResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { - var data ExampleResourceModel - - // Read Terraform plan data into the model - resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) - - if resp.Diagnostics.HasError() { - return - } - - // If applicable, this is a great opportunity to initialize any necessary - // provider client data and make a call using it. - // httpResp, err := r.client.Do(httpReq) - // if err != nil { - // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create example, got error: %s", err)) - // return - // } - - // For the purposes of this example code, hardcoding a response value to - // save into the Terraform state. - data.ID = types.StringValue("example-id") - - // Write logs using the tflog package - // Documentation: https://terraform.io/plugin/log - tflog.Trace(ctx, "created a resource") - - // Save data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} - -// Read is called when the resource is read or refreshed. -func (r *ExampleResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { - var data ExampleResourceModel - - // Read Terraform prior state data into the model - resp.Diagnostics.Append(req.State.Get(ctx, &data)...) - - if resp.Diagnostics.HasError() { - return - } - - // If applicable, this is a great opportunity to initialize any necessary - // provider client data and make a call using it. - // httpResp, err := r.client.Do(httpReq) - // if err != nil { - // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to read example, got error: %s", err)) - // return - // } - - // Save updated data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} - -// Update is called when the resource is updated. -func (r *ExampleResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { - var data ExampleResourceModel - - // Read Terraform plan data into the model - resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) - - if resp.Diagnostics.HasError() { - return - } - - // If applicable, this is a great opportunity to initialize any necessary - // provider client data and make a call using it. - // httpResp, err := r.client.Do(httpReq) - // if err != nil { - // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to update example, got error: %s", err)) - // return - // } - - // Save updated data into Terraform state - resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) -} - -// Delete is called when the resource is destroyed. -func (r *ExampleResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - var data ExampleResourceModel - - // Read Terraform prior state data into the model - resp.Diagnostics.Append(req.State.Get(ctx, &data)...) - - if resp.Diagnostics.HasError() { - return - } - - // If applicable, this is a great opportunity to initialize any necessary - // provider client data and make a call using it. - // httpResp, err := r.client.Do(httpReq) - // if err != nil { - // resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to delete example, got error: %s", err)) - // return - // } -} - -// ImportState imports to the resource. -func (r *ExampleResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { - resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) -} diff --git a/terraform-provider-constellation/internal/provider/image_data_source.go b/terraform-provider-constellation/internal/provider/image_data_source.go index 52fb09ac9..2996c9e9e 100644 --- a/terraform-provider-constellation/internal/provider/image_data_source.go +++ b/terraform-provider-constellation/internal/provider/image_data_source.go @@ -13,11 +13,9 @@ import ( "github.com/edgelesssys/constellation/v2/internal/attestation/variant" "github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider" "github.com/edgelesssys/constellation/v2/internal/imagefetcher" - "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -46,7 +44,6 @@ type imageFetcher interface { // ImageDataSourceModel defines the image data source's data model. type ImageDataSourceModel struct { - ID types.String `tfsdk:"id"` // Required for testing. AttestationVariant types.String `tfsdk:"attestation_variant"` ImageVersion types.String `tfsdk:"image_version"` CSP types.String `tfsdk:"csp"` @@ -65,35 +62,13 @@ func (d *ImageDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, Description: "Data source to retrieve the Constellation OS image reference for a given CSP and Attestation Variant.", MarkdownDescription: "Data source to retrieve the Constellation OS image reference for a given CSP and Attestation Variant.", Attributes: map[string]schema.Attribute{ - "id": schema.StringAttribute{ - Computed: true, - }, - "attestation_variant": schema.StringAttribute{ - Description: "Attestation variant the image should work with. (e.g. `azure-sev-snp`)", - MarkdownDescription: "Attestation variant the image should work with. Can be one of:\n" + - " * `aws-sev-snp`\n" + - " * `aws-nitro-tpm`\n" + - " * `azure-sev-snp`\n" + - " * `gcp-sev-es`\n", - Required: true, - Validators: []validator.String{ - stringvalidator.OneOf("aws-sev-snp", "aws-nitro-tpm", "azure-sev-snp", "gcp-sev-es"), - }, - }, + "attestation_variant": newAttestationVariantAttribute(attributeInput), "image_version": schema.StringAttribute{ Description: "Version of the Constellation OS image to use. (e.g. `v2.13.0`)", MarkdownDescription: "Version of the Constellation OS image to use. (e.g. `v2.13.0`)", Required: true, // TODO(msanft): Make this optional to support "lockstep" mode. }, - "csp": schema.StringAttribute{ - Description: "CSP (Cloud Service Provider) to use. (e.g. `azure`)", - MarkdownDescription: "CSP (Cloud Service Provider) to use. (e.g. `azure`)\n" + - "See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports.", - Required: true, - Validators: []validator.String{ - stringvalidator.OneOf("aws", "azure", "gcp"), - }, - }, + "csp": newCSPAttribute(), "region": schema.StringAttribute{ Description: "Region to retrieve the image for. Only required for AWS.", MarkdownDescription: "Region to retrieve the image for. Only required for AWS.\n" + diff --git a/terraform-provider-constellation/internal/provider/provider.go b/terraform-provider-constellation/internal/provider/provider.go index fdf496733..41023cb59 100644 --- a/terraform-provider-constellation/internal/provider/provider.go +++ b/terraform-provider-constellation/internal/provider/provider.go @@ -78,7 +78,7 @@ func (p *ConstellationProvider) Configure(ctx context.Context, req provider.Conf // Resources lists the resources implemented by the provider. func (p *ConstellationProvider) Resources(_ context.Context) []func() resource.Resource { return []func() resource.Resource{ - NewExampleResource, + NewClusterResource, } } diff --git a/terraform-provider-constellation/internal/provider/shared_attributes.go b/terraform-provider-constellation/internal/provider/shared_attributes.go new file mode 100644 index 000000000..5d010a614 --- /dev/null +++ b/terraform-provider-constellation/internal/provider/shared_attributes.go @@ -0,0 +1,125 @@ +/* +Copyright (c) Edgeless Systems GmbH + +SPDX-License-Identifier: AGPL-3.0-only +*/ + +package provider + +import ( + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +const ( + // attributeInput is the attribute type used for input variables. + attributeInput attributeType = true + // attributeOutput is the attribute type used for output variables. + attributeOutput attributeType = false +) + +type attributeType bool + +func newAttestationVariantAttribute(t attributeType) schema.Attribute { + isInput := bool(t) + return schema.StringAttribute{ + Description: "Attestation variant the image should work with. (e.g. `azure-sev-snp`)", + MarkdownDescription: "Attestation variant the image should work with. Can be one of:\n" + + " * `aws-sev-snp`\n" + + " * `aws-nitro-tpm`\n" + + " * `azure-sev-snp`\n" + + " * `gcp-sev-es`\n", + Required: isInput, + Computed: !isInput, + Validators: []validator.String{ + stringvalidator.OneOf("aws-sev-snp", "aws-nitro-tpm", "azure-sev-snp", "gcp-sev-es"), + }, + } +} + +func newCSPAttribute() schema.Attribute { + return schema.StringAttribute{ + Description: "CSP (Cloud Service Provider) to use. (e.g. `azure`)", + MarkdownDescription: "CSP (Cloud Service Provider) to use. (e.g. `azure`)\n" + + "See the [full list of CSPs](https://docs.edgeless.systems/constellation/overview/clouds) that Constellation supports.", + Required: true, + Validators: []validator.String{ + stringvalidator.OneOf("aws", "azure", "gcp"), + }, + } +} + +func newMeasurementsAttribute(t attributeType) schema.Attribute { + isInput := bool(t) + return schema.MapNestedAttribute{ + Computed: !isInput, + Required: isInput, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "expected": schema.StringAttribute{ + Required: isInput, + Computed: !isInput, + }, + "warn_only": schema.BoolAttribute{ + Required: isInput, + Computed: !isInput, + }, + }, + }, + } +} + +func newAttestationConfigAttribute(t attributeType) schema.Attribute { + isInput := bool(t) + return schema.SingleNestedAttribute{ + Computed: !isInput, + Required: isInput, + MarkdownDescription: "Attestation comprises the measurements and SEV-SNP specific parameters.", + Description: "The values provide sensible defaults. See the docs for advanced usage.", // TODO(elchead): AB#3568 + Attributes: map[string]schema.Attribute{ + "variant": newAttestationVariantAttribute(t), // duplicated for convenience in cluster resource + "bootloader_version": schema.Int64Attribute{ + Computed: !isInput, + Required: isInput, + }, + "tee_version": schema.Int64Attribute{ + Computed: !isInput, + Required: isInput, + }, + "snp_version": schema.Int64Attribute{ + Computed: !isInput, + Required: isInput, + }, + "microcode_version": schema.Int64Attribute{ + Computed: !isInput, + Required: isInput, + }, + "azure_firmware_signer_config": schema.SingleNestedAttribute{ + Computed: !isInput, + Optional: isInput, + Attributes: map[string]schema.Attribute{ + "accepted_key_digests": schema.ListAttribute{ + Computed: !isInput, + Optional: isInput, + ElementType: types.StringType, + }, + "enforcement_policy": schema.StringAttribute{ + Computed: !isInput, + Optional: isInput, + }, + "maa_url": schema.StringAttribute{ + Computed: !isInput, + Optional: isInput, + }, + }, + }, + "amd_root_key": schema.StringAttribute{ + Computed: !isInput, + Required: isInput, + }, + "measurements": newMeasurementsAttribute(t), + }, + } +}