diff --git a/.github/actions/self_managed_create/action.yml b/.github/actions/self_managed_create/action.yml index d06d982a2..354f7220c 100644 --- a/.github/actions/self_managed_create/action.yml +++ b/.github/actions/self_managed_create/action.yml @@ -50,11 +50,10 @@ runs: } }" >> terraform.tfvars if [[ "${{ inputs.cloudProvider }}" == 'aws' ]]; then - echo "iam_instance_profile_control_plane = \"$(yq '.provider.aws.iamProfileControlPlane' constellation-conf.yaml)\"" >> terraform.tfvars - echo "iam_instance_profile_worker_nodes = \"$(yq '.provider.aws.iamProfileWorkerNodes' constellation-conf.yaml)\"" >> terraform.tfvars + echo "iam_instance_profile_name_control_plane = \"$(yq '.provider.aws.iamProfileControlPlane' constellation-conf.yaml)\"" >> terraform.tfvars + echo "iam_instance_profile_name_worker_nodes = \"$(yq '.provider.aws.iamProfileWorkerNodes' constellation-conf.yaml)\"" >> terraform.tfvars echo "region = \"$(yq '.provider.aws.region' constellation-conf.yaml)\"" >> terraform.tfvars echo "zone = \"$(yq '.provider.aws.zone' constellation-conf.yaml)\"" >> terraform.tfvars - echo "ami = \"${{ steps.get_image.outputs.image_ref }}\"" >> terraform.tfvars echo "enable_snp = $(yq '.attestation | has("awsSEVSNP")' constellation-conf.yaml)" >> terraform.tfvars elif [[ "${{ inputs.cloudProvider }}" == 'azure' ]]; then echo "location = \"$(yq '.provider.azure.location' constellation-conf.yaml)\"" >> terraform.tfvars @@ -84,17 +83,17 @@ runs: working-directory: ${{ github.workspace }}/e2e-infra if: inputs.cloudProvider == 'azure' run: | - constellation maa-patch $(terraform output attestationURL | jq -r) + constellation maa-patch $(terraform output attestation_url | jq -r) - name: Write outputs to state file shell: bash working-directory: ${{ github.workspace }}/e2e-infra run: | yq eval '.version ="v1"' --inplace ${{ github.workspace }}/constellation-state.yaml - yq eval ".infrastructure.initSecret =\"$(terraform output initSecret | jq -r | tr -d '\n' | hexdump -ve '/1 "%02x"' && echo '')\"" --inplace ${{ github.workspace }}/constellation-state.yaml + yq eval ".infrastructure.initSecret =\"$(terraform output init_secret | jq -r | tr -d '\n' | hexdump -ve '/1 "%02x"' && echo '')\"" --inplace ${{ github.workspace }}/constellation-state.yaml yq eval ".infrastructure.clusterEndpoint =\"$(terraform output out_of_cluster_endpoint | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml yq eval ".infrastructure.inClusterEndpoint =\"$(terraform output in_cluster_endpoint | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml - yq eval ".infrastructure.ipCidrNode =\"$(terraform output ip_cidr_nodes | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml + yq eval ".infrastructure.ipCidrNode =\"$(terraform output ip_cidr_node | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml yq eval ".infrastructure.uid =\"$(terraform output uid | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml yq eval ".infrastructure.name =\"$(terraform output name | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml yq eval ".infrastructure.apiServerCertSANs =$(terraform output -json api_server_cert_sans)" --inplace ${{ github.workspace }}/constellation-state.yaml @@ -104,8 +103,8 @@ runs: yq eval ".infrastructure.azure.networkSecurityGroupName =\"$(terraform output network_security_group_name | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml yq eval ".infrastructure.azure.loadBalancerName =\"$(terraform output loadbalancer_name | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml yq eval ".infrastructure.azure.userAssignedIdentity =\"$(terraform output user_assigned_identity_client_id | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml - yq eval ".infrastructure.azure.attestationURL =\"$(terraform output attestationURL | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml + yq eval ".infrastructure.azure.attestationURL =\"$(terraform output attestation_url | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml elif [[ "${{ inputs.cloudProvider }}" == 'gcp' ]]; then yq eval ".infrastructure.gcp.projectID =\"$(terraform output project | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml - yq eval ".infrastructure.gcp.ipCidrPod =\"$(terraform output ip_cidr_pods | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml + yq eval ".infrastructure.gcp.ipCidrPod =\"$(terraform output ip_cidr_pod | jq -r)\"" --inplace ${{ github.workspace }}/constellation-state.yaml fi diff --git a/cli/internal/cloudcmd/iam.go b/cli/internal/cloudcmd/iam.go index 529e329b7..e5902c842 100644 --- a/cli/internal/cloudcmd/iam.go +++ b/cli/internal/cloudcmd/iam.go @@ -31,7 +31,7 @@ func NewIAMDestroyer() *IAMDestroyer { return &IAMDestroyer{newTerraformClient: newTerraformIAMClient} } -// GetTfStateServiceAccountKey returns the sa_key output from the terraform state. +// GetTfStateServiceAccountKey returns the service_account_key output from the terraform state. func (d *IAMDestroyer) GetTfStateServiceAccountKey(ctx context.Context, tfWorkspace string) (gcpshared.ServiceAccountKey, error) { client, err := d.newTerraformClient(ctx, tfWorkspace) if err != nil { @@ -95,7 +95,7 @@ type GCPIAMConfig struct { // AzureIAMConfig holds the necessary values for Azure IAM configuration. type AzureIAMConfig struct { - Region string + Location string ServicePrincipal string ResourceGroup string } @@ -167,7 +167,7 @@ func (c *IAMCreator) createAzure(ctx context.Context, cl tfIAMClient, opts *IAMC defer rollbackOnError(c.out, &retErr, &rollbackerTerraform{client: cl}, opts.TFLogLevel) vars := terraform.AzureIAMVariables{ - Region: opts.Azure.Region, + Location: opts.Azure.Location, ResourceGroup: opts.Azure.ResourceGroup, ServicePrincipal: opts.Azure.ServicePrincipal, } diff --git a/cli/internal/cloudcmd/iam_test.go b/cli/internal/cloudcmd/iam_test.go index 628bd2caf..ff198c51c 100644 --- a/cli/internal/cloudcmd/iam_test.go +++ b/cli/internal/cloudcmd/iam_test.go @@ -40,7 +40,7 @@ func TestIAMCreator(t *testing.T) { } validAzureIAMConfig := AzureIAMConfig{ - Region: "westus", + Location: "westus", ServicePrincipal: "constell-test", ResourceGroup: "constell-test", } diff --git a/cli/internal/cloudcmd/tfvars.go b/cli/internal/cloudcmd/tfvars.go index d56dded85..4b78f7df8 100644 --- a/cli/internal/cloudcmd/tfvars.go +++ b/cli/internal/cloudcmd/tfvars.go @@ -64,6 +64,14 @@ func TerraformIAMUpgradeVars(conf *config.Config, fileHandler file.Handler) (ter if err := terraform.VariablesFromBytes(oldVarBytes, &oldVars); err != nil { return nil, fmt.Errorf("parsing existing IAM workspace: %w", err) } + + // Migration from the "region" to the "location" field na. + // TODO(msanft): Remove after v2.14.0 is released. + if oldVars.Region != nil && *oldVars.Region != "" && oldVars.Location == "" { + oldVars.Location = *oldVars.Region + oldVars.Region = nil + } + vars = azureTerraformIAMVars(conf, oldVars) case cloudprovider.GCP: var oldVars terraform.GCPIAMVariables @@ -96,7 +104,7 @@ func awsTerraformVars(conf *config.Config, imageRef string) *terraform.AWSCluste NodeGroups: nodeGroups, Region: conf.Provider.AWS.Region, Zone: conf.Provider.AWS.Zone, - AMIImageID: imageRef, + ImageID: imageRef, IAMProfileControlPlane: conf.Provider.AWS.IAMProfileControlPlane, IAMProfileWorkerNodes: conf.Provider.AWS.IAMProfileWorkerNodes, Debug: conf.IsDebugCluster(), @@ -188,7 +196,7 @@ func azureTerraformVars(conf *config.Config, imageRef string) (*terraform.AzureC func azureTerraformIAMVars(conf *config.Config, oldVars terraform.AzureIAMVariables) *terraform.AzureIAMVariables { return &terraform.AzureIAMVariables{ - Region: conf.Provider.Azure.Location, + Location: conf.Provider.Azure.Location, ServicePrincipal: oldVars.ServicePrincipal, ResourceGroup: conf.Provider.Azure.ResourceGroup, } diff --git a/cli/internal/cmd/iamcreate_test.go b/cli/internal/cmd/iamcreate_test.go index f4ab13627..19aba50db 100644 --- a/cli/internal/cmd/iamcreate_test.go +++ b/cli/internal/cmd/iamcreate_test.go @@ -75,7 +75,7 @@ func TestIAMCreateAWS(t *testing.T) { CloudProvider: cloudprovider.AWS, AWSOutput: cloudcmd.AWSIAMOutput{ ControlPlaneInstanceProfile: "test_control_plane_instance_profile", - WorkerNodeInstanceProfile: "test_worker_nodes_instance_profile", + WorkerNodeInstanceProfile: "test_worker_nodes_instance_profile_name", }, } diff --git a/cli/internal/cmd/iamcreateazure.go b/cli/internal/cmd/iamcreateazure.go index 6c82c10f6..d80bcb654 100644 --- a/cli/internal/cmd/iamcreateazure.go +++ b/cli/internal/cmd/iamcreateazure.go @@ -75,7 +75,7 @@ type azureIAMCreator struct { func (c *azureIAMCreator) getIAMConfigOptions() *cloudcmd.IAMConfigOptions { return &cloudcmd.IAMConfigOptions{ Azure: cloudcmd.AzureIAMConfig{ - Region: c.flags.region, + Location: c.flags.region, ResourceGroup: c.flags.resourceGroup, ServicePrincipal: c.flags.servicePrincipal, }, diff --git a/cli/internal/cmd/iamupgradeapply_test.go b/cli/internal/cmd/iamupgradeapply_test.go index 81d0e14b0..e1d4c19ce 100644 --- a/cli/internal/cmd/iamupgradeapply_test.go +++ b/cli/internal/cmd/iamupgradeapply_test.go @@ -37,7 +37,7 @@ func TestIamUpgradeApply(t *testing.T) { require.NoError(t, fh.Write( filepath.Join(constants.TerraformIAMWorkingDir, "terraform.tfvars"), []byte( - "region = \"foo\"\n"+ + "location = \"foo\"\n"+ "resource_group_name = \"bar\"\n"+ "service_principal_name = \"baz\"\n", ), diff --git a/cli/internal/terraform/terraform.go b/cli/internal/terraform/terraform.go index 8d64f73ba..58ce818e1 100644 --- a/cli/internal/terraform/terraform.go +++ b/cli/internal/terraform/terraform.go @@ -95,13 +95,13 @@ func (c *Client) ShowIAM(ctx context.Context, provider cloudprovider.Provider) ( switch provider { case cloudprovider.GCP: - saKeyOutputRaw, ok := tfState.Values.Outputs["sa_key"] + saKeyOutputRaw, ok := tfState.Values.Outputs["service_account_key"] if !ok { - return IAMOutput{}, errors.New("no service account key output found") + return IAMOutput{}, errors.New("no service_account_key output found") } saKeyOutput, ok := saKeyOutputRaw.Value.(string) if !ok { - return IAMOutput{}, errors.New("invalid type in service account key output: not a string") + return IAMOutput{}, errors.New("invalid type in service_account_key output: not a string") } return IAMOutput{ GCP: GCPIAMOutput{ @@ -111,27 +111,27 @@ func (c *Client) ShowIAM(ctx context.Context, provider cloudprovider.Provider) ( case cloudprovider.Azure: subscriptionIDRaw, ok := tfState.Values.Outputs["subscription_id"] if !ok { - return IAMOutput{}, errors.New("no subscription id output found") + return IAMOutput{}, errors.New("no subscription_id output found") } subscriptionIDOutput, ok := subscriptionIDRaw.Value.(string) if !ok { - return IAMOutput{}, errors.New("invalid type in subscription id output: not a string") + return IAMOutput{}, errors.New("invalid type in subscription_id output: not a string") } tenantIDRaw, ok := tfState.Values.Outputs["tenant_id"] if !ok { - return IAMOutput{}, errors.New("no tenant id output found") + return IAMOutput{}, errors.New("no tenant_id output found") } tenantIDOutput, ok := tenantIDRaw.Value.(string) if !ok { - return IAMOutput{}, errors.New("invalid type in tenant id output: not a string") + return IAMOutput{}, errors.New("invalid type in tenant_id output: not a string") } uamiIDRaw, ok := tfState.Values.Outputs["uami_id"] if !ok { - return IAMOutput{}, errors.New("no UAMI id output found") + return IAMOutput{}, errors.New("no uami_id output found") } uamiIDOutput, ok := uamiIDRaw.Value.(string) if !ok { - return IAMOutput{}, errors.New("invalid type in UAMI id output: not a string") + return IAMOutput{}, errors.New("invalid type in uami_id output: not a string") } return IAMOutput{ Azure: AzureIAMOutput{ @@ -141,21 +141,21 @@ func (c *Client) ShowIAM(ctx context.Context, provider cloudprovider.Provider) ( }, }, nil case cloudprovider.AWS: - controlPlaneProfileRaw, ok := tfState.Values.Outputs["control_plane_instance_profile"] + controlPlaneProfileRaw, ok := tfState.Values.Outputs["iam_instance_profile_name_control_plane"] if !ok { - return IAMOutput{}, errors.New("no control plane instance profile output found") + return IAMOutput{}, errors.New("no iam_instance_profile_name_control_plane output found") } controlPlaneProfileOutput, ok := controlPlaneProfileRaw.Value.(string) if !ok { - return IAMOutput{}, errors.New("invalid type in control plane instance profile output: not a string") + return IAMOutput{}, errors.New("invalid type in iam_instance_profile_name_control_plane output: not a string") } - workerNodeProfileRaw, ok := tfState.Values.Outputs["worker_nodes_instance_profile"] + workerNodeProfileRaw, ok := tfState.Values.Outputs["iam_instance_profile_name_worker_nodes"] if !ok { - return IAMOutput{}, errors.New("no worker node instance profile output found") + return IAMOutput{}, errors.New("no iam_instance_profile_name_worker_nodes output found") } workerNodeProfileOutput, ok := workerNodeProfileRaw.Value.(string) if !ok { - return IAMOutput{}, errors.New("invalid type in worker node instance profile output: not a string") + return IAMOutput{}, errors.New("invalid type in iam_instance_profile_name_worker_nodes output: not a string") } return IAMOutput{ AWS: AWSIAMOutput{ @@ -209,13 +209,13 @@ func (c *Client) ShowInfrastructure(ctx context.Context, provider cloudprovider. return state.Infrastructure{}, fmt.Errorf("convert api_server_cert_sans output: %w", err) } - secretOutput, ok := tfState.Values.Outputs["initSecret"] + secretOutput, ok := tfState.Values.Outputs["init_secret"] if !ok { - return state.Infrastructure{}, errors.New("no initSecret output found") + return state.Infrastructure{}, errors.New("no init_secret output found") } secret, ok := secretOutput.Value.(string) if !ok { - return state.Infrastructure{}, errors.New("invalid type in initSecret output: not a string") + return state.Infrastructure{}, errors.New("invalid type in init_Secret output: not a string") } uidOutput, ok := tfState.Values.Outputs["uid"] @@ -236,13 +236,13 @@ func (c *Client) ShowInfrastructure(ctx context.Context, provider cloudprovider. return state.Infrastructure{}, errors.New("invalid type in name output: not a string") } - cidrNodesOutput, ok := tfState.Values.Outputs["ip_cidr_nodes"] + cidrNodesOutput, ok := tfState.Values.Outputs["ip_cidr_node"] if !ok { - return state.Infrastructure{}, errors.New("no ip_cidr_nodes output found") + return state.Infrastructure{}, errors.New("no ip_cidr_node output found") } cidrNodes, ok := cidrNodesOutput.Value.(string) if !ok { - return state.Infrastructure{}, errors.New("invalid type in ip_cidr_nodes output: not a string") + return state.Infrastructure{}, errors.New("invalid type in ip_cidr_node output: not a string") } res := state.Infrastructure{ @@ -266,13 +266,13 @@ func (c *Client) ShowInfrastructure(ctx context.Context, provider cloudprovider. return state.Infrastructure{}, errors.New("invalid type in project output: not a string") } - cidrPodsOutput, ok := tfState.Values.Outputs["ip_cidr_pods"] + cidrPodsOutput, ok := tfState.Values.Outputs["ip_cidr_pod"] if !ok { - return state.Infrastructure{}, errors.New("no ip_cidr_pods output found") + return state.Infrastructure{}, errors.New("no ip_cidr_pod output found") } cidrPods, ok := cidrPodsOutput.Value.(string) if !ok { - return state.Infrastructure{}, errors.New("invalid type in ip_cidr_pods output: not a string") + return state.Infrastructure{}, errors.New("invalid type in ip_cidr_pod output: not a string") } res.GCP = &state.GCP{ @@ -280,13 +280,13 @@ func (c *Client) ShowInfrastructure(ctx context.Context, provider cloudprovider. IPCidrPod: cidrPods, } case cloudprovider.Azure: - attestationURLOutput, ok := tfState.Values.Outputs["attestationURL"] + attestationURLOutput, ok := tfState.Values.Outputs["attestation_url"] if !ok { - return state.Infrastructure{}, errors.New("no attestationURL output found") + return state.Infrastructure{}, errors.New("no attestation_url output found") } attestationURL, ok := attestationURLOutput.Value.(string) if !ok { - return state.Infrastructure{}, errors.New("invalid type in attestationURL output: not a string") + return state.Infrastructure{}, errors.New("invalid type in attestation_url output: not a string") } azureUAMIOutput, ok := tfState.Values.Outputs["user_assigned_identity_client_id"] diff --git a/cli/internal/terraform/terraform_test.go b/cli/internal/terraform/terraform_test.go index 25192a022..d603679f3 100644 --- a/cli/internal/terraform/terraform_test.go +++ b/cli/internal/terraform/terraform_test.go @@ -122,7 +122,7 @@ func TestPrepareIAM(t *testing.T) { ServiceAccountID: "const-test-case", } azureVars := &AzureIAMVariables{ - Region: "westus", + Location: "westus", ResourceGroup: "constell-test-rg", } awsVars := &AWSIAMVariables{ @@ -218,7 +218,7 @@ func TestCreateCluster(t *testing.T) { "in_cluster_endpoint": { Value: "192.0.2.101", }, - "initSecret": { + "init_secret": { Value: "initSecret", }, "uid": { @@ -230,7 +230,7 @@ func TestCreateCluster(t *testing.T) { "name": { Value: "constell-12345abc", }, - "ip_cidr_nodes": { + "ip_cidr_node": { Value: "192.0.2.103/32", }, }, @@ -248,13 +248,13 @@ func TestCreateCluster(t *testing.T) { "in_cluster_endpoint": { Value: "192.0.2.101", }, - "initSecret": { + "init_secret": { Value: "initSecret", }, "uid": { Value: "12345abc", }, - "attestationURL": { + "attestation_url": { Value: "https://12345.neu.attest.azure.net", }, "api_server_cert_sans": { @@ -278,7 +278,7 @@ func TestCreateCluster(t *testing.T) { "name": { Value: "constell-12345abc", }, - "ip_cidr_nodes": { + "ip_cidr_node": { Value: "192.0.2.103/32", }, }, @@ -460,7 +460,7 @@ func TestCreateCluster(t *testing.T) { tf: &stubTerraform{ showState: &tfjson.State{ Values: &tfjson.StateValues{ - Outputs: map[string]*tfjson.StateOutput{"attestationURL": {Value: 42}}, + Outputs: map[string]*tfjson.StateOutput{"attestation_url": {Value: 42}}, }, }, }, @@ -506,7 +506,7 @@ func TestCreateIAM(t *testing.T) { workingState := tfjson.State{ Values: &tfjson.StateValues{ Outputs: map[string]*tfjson.StateOutput{ - "sa_key": { + "service_account_key": { Value: "12345678_abcdefg", }, "subscription_id": { @@ -524,11 +524,11 @@ func TestCreateIAM(t *testing.T) { "application_client_secret_value": { Value: "test_application_client_secret_value", }, - "control_plane_instance_profile": { - Value: "test_control_plane_instance_profile", + "iam_instance_profile_name_control_plane": { + Value: "test_iam_instance_profile_name_control_plane", }, - "worker_nodes_instance_profile": { - Value: "test_worker_nodes_instance_profile", + "iam_instance_profile_name_worker_nodes": { + Value: "test_iam_instance_profile_name_worker_nodes", }, }, }, @@ -542,7 +542,7 @@ func TestCreateIAM(t *testing.T) { ServiceAccountID: "const-test-case", } azureVars := &AzureIAMVariables{ - Region: "westus", + Location: "westus", ResourceGroup: "constell-test-rg", } awsVars := &AWSIAMVariables{ @@ -607,7 +607,7 @@ func TestCreateIAM(t *testing.T) { fs: afero.NewMemMapFs(), wantErr: true, }, - "gcp no sa_key": { + "gcp no service_account_key": { pathBase: path.Join(constants.TerraformEmbeddedDir, "iam"), provider: cloudprovider.GCP, vars: gcpVars, @@ -621,14 +621,14 @@ func TestCreateIAM(t *testing.T) { fs: afero.NewMemMapFs(), wantErr: true, }, - "gcp sa_key has wrong type": { + "gcp service_account_key has wrong type": { pathBase: path.Join(constants.TerraformEmbeddedDir, "iam"), provider: cloudprovider.GCP, vars: gcpVars, tf: &stubTerraform{ showState: &tfjson.State{ Values: &tfjson.StateValues{ - Outputs: map[string]*tfjson.StateOutput{"sa_key": {Value: 42}}, + Outputs: map[string]*tfjson.StateOutput{"service_account_key": {Value: 42}}, }, }, }, @@ -706,8 +706,8 @@ func TestCreateIAM(t *testing.T) { tf: &stubTerraform{showState: newTestState()}, fs: afero.NewMemMapFs(), want: IAMOutput{AWS: AWSIAMOutput{ - ControlPlaneInstanceProfile: "test_control_plane_instance_profile", - WorkerNodeInstanceProfile: "test_worker_nodes_instance_profile", + ControlPlaneInstanceProfile: "test_iam_instance_profile_name_control_plane", + WorkerNodeInstanceProfile: "test_iam_instance_profile_name_worker_nodes", }}, }, "aws init fails": { @@ -734,7 +734,7 @@ func TestCreateIAM(t *testing.T) { fs: afero.NewMemMapFs(), wantErr: true, }, - "aws no control_plane_instance_profile": { + "aws no iam_instance_profile_name_control_plane": { pathBase: path.Join(constants.TerraformEmbeddedDir, "iam"), provider: cloudprovider.AWS, vars: awsVars, @@ -748,14 +748,14 @@ func TestCreateIAM(t *testing.T) { fs: afero.NewMemMapFs(), wantErr: true, }, - "azure control_plane_instance_profile has wrong type": { + "azure iam_instance_profile_name_control_plane has wrong type": { pathBase: path.Join(constants.TerraformEmbeddedDir, "iam"), provider: cloudprovider.AWS, vars: awsVars, tf: &stubTerraform{ showState: &tfjson.State{ Values: &tfjson.StateValues{ - Outputs: map[string]*tfjson.StateOutput{"control_plane_instance_profile": {Value: 42}}, + Outputs: map[string]*tfjson.StateOutput{"iam_instance_profile_name_control_plane": {Value: 42}}, }, }, }, @@ -1129,7 +1129,7 @@ func TestShowIAM(t *testing.T) { "GCP success": { tf: &stubTerraform{ showState: getTfjsonState(map[string]any{ - "sa_key": "key", + "service_account_key": "key", }), }, csp: cloudprovider.GCP, @@ -1137,7 +1137,7 @@ func TestShowIAM(t *testing.T) { "GCP wrong data type": { tf: &stubTerraform{ showState: getTfjsonState(map[string]any{ - "sa_key": map[string]any{}, + "service_account_key": map[string]any{}, }), }, csp: cloudprovider.GCP, @@ -1226,45 +1226,45 @@ func TestShowIAM(t *testing.T) { "AWS success": { tf: &stubTerraform{ showState: getTfjsonState(map[string]any{ - "control_plane_instance_profile": "profile", - "worker_nodes_instance_profile": "profile", + "iam_instance_profile_name_control_plane": "profile", + "iam_instance_profile_name_worker_nodes": "profile", }), }, csp: cloudprovider.AWS, }, - "AWS wrong data type control_plane_instance_profile": { + "AWS wrong data type iam_instance_profile_name_control_plane": { tf: &stubTerraform{ showState: getTfjsonState(map[string]any{ - "control_plane_instance_profile": map[string]any{}, - "worker_nodes_instance_profile": "profile", + "iam_instance_profile_name_control_plane": map[string]any{}, + "iam_instance_profile_name_worker_nodes": "profile", }), }, csp: cloudprovider.AWS, wantErr: true, }, - "AWS wrong data type worker_nodes_instance_profile": { + "AWS wrong data type iam_instance_profile_name_worker_nodes": { tf: &stubTerraform{ showState: getTfjsonState(map[string]any{ - "control_plane_instance_profile": "profile", - "worker_nodes_instance_profile": map[string]any{}, + "iam_instance_profile_name_control_plane": "profile", + "iam_instance_profile_name_worker_nodes": map[string]any{}, }), }, csp: cloudprovider.AWS, wantErr: true, }, - "AWS missing control_plane_instance_profile": { + "AWS missing iam_instance_profile_name_control_plane": { tf: &stubTerraform{ showState: getTfjsonState(map[string]any{ - "worker_nodes_instance_profile": "profile", + "iam_instance_profile_name_worker_nodes": "profile", }), }, csp: cloudprovider.AWS, wantErr: true, }, - "AWS missing worker_nodes_instance_profile": { + "AWS missing iam_instance_profile_name_worker_nodes": { tf: &stubTerraform{ showState: getTfjsonState(map[string]any{ - "control_plane_instance_profile": "profile", + "iam_instance_profile_name_control_plane": "profile", }), }, csp: cloudprovider.AWS, diff --git a/cli/internal/terraform/variables.go b/cli/internal/terraform/variables.go index 8999784b5..6c800e124 100644 --- a/cli/internal/terraform/variables.go +++ b/cli/internal/terraform/variables.go @@ -38,8 +38,9 @@ func VariablesFromBytes[T any](b []byte, vars *T) error { return fmt.Errorf("parsing variables: %w", err) } - if err := gohcl.DecodeBody(file.Body, nil, vars); err != nil { - return fmt.Errorf("decoding variables: %w", err) + diags := gohcl.DecodeBody(file.Body, nil, vars) + if diags.HasErrors() { + return fmt.Errorf("decoding variables: %w", diags) } return nil } @@ -52,12 +53,12 @@ type AWSClusterVariables struct { Region string `hcl:"region" cty:"region"` // Zone is the AWS zone to use in the given region. Zone string `hcl:"zone" cty:"zone"` - // AMIImageID is the ID of the AMI image to use. - AMIImageID string `hcl:"ami" cty:"ami"` - // IAMGroupControlPlane is the IAM group to use for the control-plane nodes. - IAMProfileControlPlane string `hcl:"iam_instance_profile_control_plane" cty:"iam_instance_profile_control_plane"` - // IAMGroupWorkerNodes is the IAM group to use for the worker nodes. - IAMProfileWorkerNodes string `hcl:"iam_instance_profile_worker_nodes" cty:"iam_instance_profile_worker_nodes"` + // ImageID is the ID of the AMI to use. + ImageID string `hcl:"image_id" cty:"image_id"` + // IAMProfileControlPlane is the IAM group to use for the control-plane nodes. + IAMProfileControlPlane string `hcl:"iam_instance_profile_name_control_plane" cty:"iam_instance_profile_name_control_plane"` + // IAMProfileWorkerNodes is the IAM group to use for the worker nodes. + IAMProfileWorkerNodes string `hcl:"iam_instance_profile_name_worker_nodes" cty:"iam_instance_profile_name_worker_nodes"` // Debug is true if debug mode is enabled. Debug bool `hcl:"debug" cty:"debug"` // EnableSNP controls enablement of the EC2 cpu-option "AmdSevSnp". @@ -244,8 +245,11 @@ type AzureNodeGroup struct { // AzureIAMVariables is user configuration for creating the IAM configuration with Terraform on Microsoft Azure. type AzureIAMVariables struct { - // Region is the Azure region to use. (e.g. westus) - Region string `hcl:"region" cty:"region"` + // Region is the Azure location to use. (e.g. westus). + // THIS FIELD IS DEPRECATED AND ONLY KEPT FOR MIGRATION PURPOSES. DO NOT USE. + Region *string `hcl:"region" cty:"region"` // TODO(msanft): Remove this field once v2.14.0 is released. + // Location is the Azure location to use. (e.g. westus) + Location string `hcl:"location,optional" cty:"location"` // TODO(msanft): Make this required once v2.14.0 is released. // ServicePrincipal is the name of the service principal to use. ServicePrincipal string `hcl:"service_principal_name" cty:"service_principal_name"` // ResourceGroup is the name of the resource group to use. @@ -282,7 +286,7 @@ type OpenStackClusterVariables struct { // FloatingIPPoolID is the ID of the OpenStack floating IP pool to use for public IPs. FloatingIPPoolID string `hcl:"floating_ip_pool_id" cty:"floating_ip_pool_id"` // ImageURL is the URL of the OpenStack image to use. - ImageURL string `hcl:"image_url" cty:"image_url"` + ImageURL string `hcl:"image_id" cty:"image_id"` // DirectDownload decides whether to download the image directly from the URL to OpenStack or to upload it from the local machine. DirectDownload bool `hcl:"direct_download" cty:"direct_download"` // OpenstackUserDomainName is the OpenStack user domain name to use. @@ -347,7 +351,7 @@ type QEMUVariables struct { // Can be either "uefi" or "direct-linux-boot". BootMode string `hcl:"constellation_boot_mode" cty:"constellation_boot_mode"` // ImagePath is the path to the image to use for the nodes. - ImagePath string `hcl:"constellation_os_image" cty:"constellation_os_image"` + ImagePath string `hcl:"image_id" cty:"image_id"` // ImageFormat is the format of the image from ImagePath. ImageFormat string `hcl:"image_format" cty:"image_format"` // MetadataAPIImage is the container image to use for the metadata API. diff --git a/cli/internal/terraform/variables_test.go b/cli/internal/terraform/variables_test.go index 524e0cca1..30ad43e6b 100644 --- a/cli/internal/terraform/variables_test.go +++ b/cli/internal/terraform/variables_test.go @@ -7,6 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only package terraform import ( + "strings" "testing" "github.com/Azure/azure-sdk-for-go/sdk/azcore/to" @@ -38,7 +39,7 @@ func TestAWSClusterVariables(t *testing.T) { }, Region: "eu-central-1", Zone: "eu-central-1a", - AMIImageID: "ami-0123456789abcdef", + ImageID: "ami-0123456789abcdef", IAMProfileControlPlane: "arn:aws:iam::123456789012:instance-profile/cluster-name-controlplane", IAMProfileWorkerNodes: "arn:aws:iam::123456789012:instance-profile/cluster-name-worker", Debug: true, @@ -47,14 +48,14 @@ func TestAWSClusterVariables(t *testing.T) { } // test that the variables are correctly rendered - want := `name = "cluster-name" -region = "eu-central-1" -zone = "eu-central-1a" -ami = "ami-0123456789abcdef" -iam_instance_profile_control_plane = "arn:aws:iam::123456789012:instance-profile/cluster-name-controlplane" -iam_instance_profile_worker_nodes = "arn:aws:iam::123456789012:instance-profile/cluster-name-worker" -debug = true -enable_snp = true + want := `name = "cluster-name" +region = "eu-central-1" +zone = "eu-central-1a" +image_id = "ami-0123456789abcdef" +iam_instance_profile_name_control_plane = "arn:aws:iam::123456789012:instance-profile/cluster-name-controlplane" +iam_instance_profile_name_worker_nodes = "arn:aws:iam::123456789012:instance-profile/cluster-name-worker" +debug = true +enable_snp = true node_groups = { control_plane_default = { disk_size = 30 @@ -77,7 +78,7 @@ custom_endpoint = "example.com" internal_load_balancer = false ` got := vars.String() - assert.Equal(t, want, got) + assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences } func TestAWSIAMVariables(t *testing.T) { @@ -91,7 +92,7 @@ func TestAWSIAMVariables(t *testing.T) { name_prefix = "my-prefix" ` got := vars.String() - assert.Equal(t, want, got) + assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences } func TestGCPClusterVariables(t *testing.T) { @@ -152,7 +153,7 @@ custom_endpoint = "example.com" internal_load_balancer = false ` got := vars.String() - assert.Equal(t, want, got) + assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences } func TestGCPIAMVariables(t *testing.T) { @@ -170,7 +171,7 @@ zone = "eu-central-1a" service_account_id = "my-service-account" ` got := vars.String() - assert.Equal(t, want, got) + assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences } func TestAzureClusterVariables(t *testing.T) { @@ -230,23 +231,23 @@ marketplace_image = { } ` got := vars.String() - assert.Equal(t, want, got) + assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences } func TestAzureIAMVariables(t *testing.T) { vars := AzureIAMVariables{ - Region: "eu-central-1", + Location: "eu-central-1", ServicePrincipal: "my-service-principal", ResourceGroup: "my-resource-group", } // test that the variables are correctly rendered - want := `region = "eu-central-1" + want := `location = "eu-central-1" service_principal_name = "my-service-principal" resource_group_name = "my-resource-group" ` got := vars.String() - assert.Equal(t, want, got) + assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences } func TestOpenStackClusterVariables(t *testing.T) { @@ -287,7 +288,7 @@ node_groups = { } cloud = "my-cloud" floating_ip_pool_id = "fip-pool-0123456789abcdef" -image_url = "https://example.com/image.raw" +image_id = "https://example.com/image.raw" direct_download = true openstack_user_domain_name = "my-user-domain" openstack_username = "my-username" @@ -297,7 +298,7 @@ custom_endpoint = "example.com" internal_load_balancer = false ` got := vars.String() - assert.Equal(t, want, got) + assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences } func TestQEMUClusterVariables(t *testing.T) { @@ -341,7 +342,7 @@ machine = "q35" libvirt_uri = "qemu:///system" libvirt_socket_path = "/var/run/libvirt/libvirt-sock" constellation_boot_mode = "uefi" -constellation_os_image = "/var/lib/libvirt/images/cluster-name.qcow2" +image_id = "/var/lib/libvirt/images/cluster-name.qcow2" image_format = "raw" metadata_api_image = "example.com/metadata-api:latest" metadata_libvirt_uri = "qemu:///system" @@ -352,7 +353,7 @@ custom_endpoint = "example.com" internal_load_balancer = false ` got := vars.String() - assert.Equal(t, want, got) + assert.Equal(t, strings.Fields(want), strings.Fields(got)) // to ignore whitespace differences } func TestVariablesFromBytes(t *testing.T) { @@ -367,7 +368,7 @@ func TestVariablesFromBytes(t *testing.T) { assert.Equal(awsVars, loadedAWSVars) azureVars := AzureIAMVariables{ - Region: "test", + Location: "test", } var loadedAzureVars AzureIAMVariables err = VariablesFromBytes([]byte(azureVars.String()), &loadedAzureVars) diff --git a/docs/docs/workflows/config.md b/docs/docs/workflows/config.md index e52c9c0b7..165100b81 100644 --- a/docs/docs/workflows/config.md +++ b/docs/docs/workflows/config.md @@ -273,13 +273,13 @@ The following describes the configuration fields and how you obtain the required * **iamProfileControlPlane**: The name of an IAM instance profile attached to all control-plane nodes. - You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `control_plane_instance_profile`. + You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `control_plane_instance_profile_name`. Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.control_plane_policy`. * **iamProfileWorkerNodes**: The name of an IAM instance profile attached to all worker nodes. - You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `worker_nodes_instance_profile`. + You can create the resource with [Terraform](https://www.terraform.io/). For that, use the [provided Terraform script](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam) to generate the necessary profile. The profile name will be provided as Terraform output value: `worker_nodes_instance_profile_name`. Alternatively, you can create the AWS profile with a tool of your choice. Use the JSON policy in [main.tf](https://github.com/edgelesssys/constellation/tree/release/v2.2/hack/terraform/aws/iam/main.tf) in the resource `aws_iam_policy.worker_node_policy`. diff --git a/docs/docs/workflows/create.md b/docs/docs/workflows/create.md index 0eff75e4b..8fdada617 100644 --- a/docs/docs/workflows/create.md +++ b/docs/docs/workflows/create.md @@ -57,7 +57,7 @@ management tooling of your choice. You need to keep the essential functionality :::info On Azure, if the enforcement policy is set to `MAAFallback` in `constellation-config.yaml`, a manual update to the MAA provider's policy is necessary. - You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestationURL | jq -r)`, when using the minimal Terraform configuration). + You can apply the update with the following command after creating the infrastructure, with `` being the URL of the MAA provider (i.e., `$(terraform output attestation_url | jq -r)`, when using the minimal Terraform configuration). ```bash constellation maa-patch diff --git a/e2e/internal/upgrade/upgrade_test.go b/e2e/internal/upgrade/upgrade_test.go index caf6a90a9..bf9da20e2 100644 --- a/e2e/internal/upgrade/upgrade_test.go +++ b/e2e/internal/upgrade/upgrade_test.go @@ -9,6 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only package upgrade import ( + "bufio" "context" "errors" "flag" @@ -454,6 +455,9 @@ type versionContainer struct { // runCommandWithSeparateOutputs runs the given command while separating buffers for // stdout and stderr. func runCommandWithSeparateOutputs(cmd *exec.Cmd) (stdout, stderr []byte, err error) { + stdout = []byte{} + stderr = []byte{} + stdoutIn, err := cmd.StdoutPipe() if err != nil { err = fmt.Errorf("create stdout pipe: %w", err) @@ -471,21 +475,26 @@ func runCommandWithSeparateOutputs(cmd *exec.Cmd) (stdout, stderr []byte, err er return } - stdout, err = io.ReadAll(stdoutIn) - if err != nil { - err = fmt.Errorf("start command: %w", err) - return + continuouslyPrintOutput := func(r io.Reader, prefix string) { + scanner := bufio.NewScanner(r) + for scanner.Scan() { + output := scanner.Text() + fmt.Printf("%s: %s\n", prefix, output) + switch prefix { + case "stdout": + stdout = append(stdout, output...) + case "stderr": + stderr = append(stderr, output...) + } + } } - stderr, err = io.ReadAll(stderrIn) - if err != nil { - err = fmt.Errorf("start command: %w", err) - return - } + go continuouslyPrintOutput(stdoutIn, "stdout") + go continuouslyPrintOutput(stderrIn, "stderr") if err = cmd.Wait(); err != nil { err = fmt.Errorf("wait for command to finish: %w", err) } - return + return stdout, stderr, err } diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 9f31e6957..21aed1e4c 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -976,7 +976,7 @@ func TestConfigVersionCompatibility(t *testing.T) { AWS: &AWSConfig{ Region: "us-east-2", Zone: "us-east-2a", - IAMProfileControlPlane: "control_plane_instance_profile", + IAMProfileControlPlane: "control_plane_instance_profile_name", IAMProfileWorkerNodes: "node_instance_profile", }, }, diff --git a/terraform-provider-constellation/docs/resources/cluster.md b/terraform-provider-constellation/docs/resources/cluster.md index 4edab0ae7..88190f556 100644 --- a/terraform-provider-constellation/docs/resources/cluster.md +++ b/terraform-provider-constellation/docs/resources/cluster.md @@ -57,9 +57,9 @@ resource "constellation_cluster" "aws_example" { ### Optional +- `api_server_cert_sans` (List of String) List of Subject Alternative Names (SANs) for the API server certificate. Usually, this will be the out-of-cluster endpoint and the in-cluster endpoint, if existing. - `azure` (Attributes) Azure-specific configuration. (see [below for nested schema](#nestedatt--azure)) - `constellation_microservice_version` (String) The version of Constellation's microservices used within the cluster. When not set, the provider default version is used. -- `extra_api_server_cert_sans` (List of String) List of additional Subject Alternative Names (SANs) for the API server certificate. - `extra_microservices` (Attributes) Extra microservice settings. (see [below for nested schema](#nestedatt--extra_microservices)) - `gcp` (Attributes) GCP-specific configuration. (see [below for nested schema](#nestedatt--gcp)) - `in_cluster_endpoint` (String) The endpoint of the cluster. When not set, the out-of-cluster endpoint is used. diff --git a/terraform-provider-constellation/internal/provider/cluster_resource.go b/terraform-provider-constellation/internal/provider/cluster_resource.go index 7b4b38214..d7094b45a 100644 --- a/terraform-provider-constellation/internal/provider/cluster_resource.go +++ b/terraform-provider-constellation/internal/provider/cluster_resource.go @@ -60,25 +60,25 @@ type ClusterResource struct { // ClusterResourceModel describes the resource data model. type ClusterResourceModel struct { - Name types.String `tfsdk:"name"` - CSP types.String `tfsdk:"csp"` - UID types.String `tfsdk:"uid"` - ImageVersion types.String `tfsdk:"image_version"` - ImageReference types.String `tfsdk:"image_reference"` - KubernetesVersion types.String `tfsdk:"kubernetes_version"` - MicroserviceVersion types.String `tfsdk:"constellation_microservice_version"` - OutOfClusterEndpoint types.String `tfsdk:"out_of_cluster_endpoint"` - InClusterEndpoint types.String `tfsdk:"in_cluster_endpoint"` - ExtraMicroservices types.Object `tfsdk:"extra_microservices"` - ExtraAPIServerCertSANs types.List `tfsdk:"extra_api_server_cert_sans"` - NetworkConfig types.Object `tfsdk:"network_config"` - MasterSecret types.String `tfsdk:"master_secret"` - MasterSecretSalt types.String `tfsdk:"master_secret_salt"` - MeasurementSalt types.String `tfsdk:"measurement_salt"` - InitSecret types.String `tfsdk:"init_secret"` - Attestation types.Object `tfsdk:"attestation"` - GCP types.Object `tfsdk:"gcp"` - Azure types.Object `tfsdk:"azure"` + Name types.String `tfsdk:"name"` + CSP types.String `tfsdk:"csp"` + UID types.String `tfsdk:"uid"` + ImageVersion types.String `tfsdk:"image_version"` + ImageReference types.String `tfsdk:"image_reference"` + KubernetesVersion types.String `tfsdk:"kubernetes_version"` + MicroserviceVersion types.String `tfsdk:"constellation_microservice_version"` + OutOfClusterEndpoint types.String `tfsdk:"out_of_cluster_endpoint"` + InClusterEndpoint types.String `tfsdk:"in_cluster_endpoint"` + ExtraMicroservices types.Object `tfsdk:"extra_microservices"` + APIServerCertSANs types.List `tfsdk:"api_server_cert_sans"` + NetworkConfig types.Object `tfsdk:"network_config"` + MasterSecret types.String `tfsdk:"master_secret"` + MasterSecretSalt types.String `tfsdk:"master_secret_salt"` + MeasurementSalt types.String `tfsdk:"measurement_salt"` + InitSecret types.String `tfsdk:"init_secret"` + Attestation types.Object `tfsdk:"attestation"` + GCP types.Object `tfsdk:"gcp"` + Azure types.Object `tfsdk:"azure"` OwnerID types.String `tfsdk:"owner_id"` ClusterID types.String `tfsdk:"cluster_id"` @@ -178,11 +178,12 @@ func (r *ClusterResource) Schema(_ context.Context, _ resource.SchemaRequest, re }, }, }, - "extra_api_server_cert_sans": schema.ListAttribute{ - MarkdownDescription: "List of additional Subject Alternative Names (SANs) for the API server certificate.", - Description: "List of additional Subject Alternative Names (SANs) for the API server certificate.", - ElementType: types.StringType, - Optional: true, + "api_server_cert_sans": schema.ListAttribute{ + MarkdownDescription: "List of Subject Alternative Names (SANs) for the API server certificate. Usually, this will be" + + " the out-of-cluster endpoint and the in-cluster endpoint, if existing.", + Description: "List of Subject Alternative Names (SANs) for the API server certificate.", + ElementType: types.StringType, + Optional: true, }, "network_config": schema.SingleNestedAttribute{ MarkdownDescription: "Configuration for the cluster's network.", @@ -503,8 +504,8 @@ func (r *ClusterResource) apply(ctx context.Context, data *ClusterResourceModel, } // parse API server certificate SANs - apiServerCertSANs := make([]string, 0, len(data.ExtraAPIServerCertSANs.Elements())) - for _, san := range data.ExtraAPIServerCertSANs.Elements() { + apiServerCertSANs := make([]string, 0, len(data.APIServerCertSANs.Elements())) + for _, san := range data.APIServerCertSANs.Elements() { apiServerCertSANs = append(apiServerCertSANs, san.String()) } diff --git a/terraform/BUILD.bazel b/terraform/BUILD.bazel index ef22922f1..74d83041e 100644 --- a/terraform/BUILD.bazel +++ b/terraform/BUILD.bazel @@ -9,13 +9,10 @@ go_library( "infrastructure/aws/modules/instance_group/main.tf", "infrastructure/aws/modules/instance_group/variables.tf", "infrastructure/aws/modules/jump_host/main.tf", - "infrastructure/aws/modules/jump_host/output.tf", "infrastructure/aws/modules/jump_host/variables.tf", "infrastructure/aws/modules/load_balancer_target/main.tf", - "infrastructure/aws/modules/load_balancer_target/output.tf", "infrastructure/aws/modules/load_balancer_target/variables.tf", "infrastructure/aws/modules/public_private_subnet/main.tf", - "infrastructure/aws/modules/public_private_subnet/output.tf", "infrastructure/aws/modules/public_private_subnet/variables.tf", "infrastructure/aws/outputs.tf", "infrastructure/aws/variables.tf", @@ -46,17 +43,14 @@ go_library( "infrastructure/gcp/outputs.tf", "infrastructure/gcp/variables.tf", "infrastructure/iam/aws/.terraform.lock.hcl", - "infrastructure/iam/aws/README.md", "infrastructure/iam/aws/main.tf", "infrastructure/iam/aws/outputs.tf", "infrastructure/iam/aws/variables.tf", "infrastructure/iam/azure/.terraform.lock.hcl", - "infrastructure/iam/azure/README.md", "infrastructure/iam/azure/main.tf", "infrastructure/iam/azure/outputs.tf", "infrastructure/iam/azure/variables.tf", "infrastructure/iam/gcp/.terraform.lock.hcl", - "infrastructure/iam/gcp/README.md", "infrastructure/iam/gcp/main.tf", "infrastructure/iam/gcp/outputs.tf", "infrastructure/iam/gcp/variables.tf", @@ -78,6 +72,9 @@ go_library( "infrastructure/qemu/modules/instance_group/variables.tf", "infrastructure/qemu/outputs.tf", "infrastructure/qemu/variables.tf", + "infrastructure/aws/modules/jump_host/output.tf", + "infrastructure/aws/modules/load_balancer_target/output.tf", + "infrastructure/aws/modules/public_private_subnet/output.tf", ], importpath = "github.com/edgelesssys/constellation/v2/terraform", visibility = ["//visibility:public"], diff --git a/terraform/infrastructure/aws/main.tf b/terraform/infrastructure/aws/main.tf index 05d042fd8..ac337a305 100644 --- a/terraform/infrastructure/aws/main.tf +++ b/terraform/infrastructure/aws/main.tf @@ -11,7 +11,6 @@ terraform { } } -# Configure the AWS Provider provider "aws" { region = var.region } @@ -19,7 +18,7 @@ provider "aws" { locals { uid = random_id.uid.hex name = "${var.name}-${local.uid}" - initSecretHash = random_password.initSecret.bcrypt_hash + init_secret_hash = random_password.init_secret.bcrypt_hash cidr_vpc_subnet_nodes = "192.168.176.0/20" ports_node_range = "30000-32767" load_balancer_ports = flatten([ @@ -38,8 +37,8 @@ locals { worker : [] } iam_instance_profile = { - control-plane : var.iam_instance_profile_control_plane - worker : var.iam_instance_profile_worker_nodes + control-plane : var.iam_instance_profile_name_control_plane + worker : var.iam_instance_profile_name_worker_nodes } # zones are all availability zones that are used by the node groups zones = distinct(sort([ @@ -61,7 +60,7 @@ resource "random_id" "uid" { byte_length = 4 } -resource "random_password" "initSecret" { +resource "random_password" "init_secret" { length = 32 special = true override_special = "_%@" @@ -172,7 +171,7 @@ resource "aws_cloudwatch_log_group" "log_group" { module "load_balancer_targets" { for_each = { for port in local.load_balancer_ports : port.name => port } source = "./modules/load_balancer_target" - name = "${local.name}-${each.value.name}" + base_name = "${local.name}-${each.value.name}" port = each.value.port healthcheck_protocol = each.value.health_check healthcheck_path = each.value.name == "kubernetes" ? "/readyz" : "" @@ -191,7 +190,7 @@ module "instance_group" { uid = local.uid instance_type = each.value.instance_type initial_count = each.value.initial_count - image_id = var.ami + image_id = var.image_id state_disk_type = each.value.disk_type state_disk_size = each.value.disk_size target_group_arns = local.target_group_arns[each.value.role] @@ -205,7 +204,7 @@ module "instance_group" { { constellation-role = each.value.role }, { constellation-node-group = each.key }, { constellation-uid = local.uid }, - { constellation-init-secret-hash = local.initSecretHash }, + { constellation-init-secret-hash = local.init_secret_hash }, { "kubernetes.io/cluster/${local.name}" = "owned" } ) } @@ -217,42 +216,6 @@ module "jump_host" { subnet_id = module.public_private_subnet.public_subnet_id[var.zone] lb_internal_ip = aws_lb.front_end.dns_name ports = [for port in local.load_balancer_ports : port.port] - iam_instance_profile = var.iam_instance_profile_worker_nodes security_groups = [aws_security_group.security_group.id] -} - -# TODO(31u3r): Remove once 2.12 is released -moved { - from = module.load_balancer_target_konnectivity - to = module.load_balancer_targets["konnectivity"] -} - -moved { - from = module.load_balancer_target_verify - to = module.load_balancer_targets["verify"] -} - -moved { - from = module.load_balancer_target_recovery - to = module.load_balancer_targets["recovery"] -} - -moved { - from = module.load_balancer_target_join - to = module.load_balancer_targets["join"] -} - -moved { - from = module.load_balancer_target_debugd[0] - to = module.load_balancer_targets["debugd"] -} - -moved { - from = module.load_balancer_target_kubernetes - to = module.load_balancer_targets["kubernetes"] -} - -moved { - from = module.load_balancer_target_bootstrapper - to = module.load_balancer_targets["bootstrapper"] + iam_instance_profile = var.iam_instance_profile_name_worker_nodes } diff --git a/terraform/infrastructure/aws/modules/instance_group/variables.tf b/terraform/infrastructure/aws/modules/instance_group/variables.tf index 15e4420fd..3c6082c7f 100644 --- a/terraform/infrastructure/aws/modules/instance_group/variables.tf +++ b/terraform/infrastructure/aws/modules/instance_group/variables.tf @@ -10,7 +10,7 @@ variable "node_group_name" { variable "role" { type = string - description = "The role of the instance group." + description = "Role of the instance group." validation { condition = contains(["control-plane", "worker"], var.role) error_message = "The role has to be 'control-plane' or 'worker'." @@ -19,7 +19,7 @@ variable "role" { variable "uid" { type = string - description = "UID of the cluster. This is used for tags." + description = "Unique Identifier (UID) of the cluster." } variable "instance_type" { @@ -34,7 +34,7 @@ variable "initial_count" { variable "image_id" { type = string - description = "Image ID for the nodes." + description = "Amazon Machine Image (AMI) ID for the cluster's nodes." } variable "state_disk_type" { @@ -64,18 +64,18 @@ variable "iam_instance_profile" { variable "security_groups" { type = list(string) - description = "List of IDs of the security groups for an instance." + description = "List of security group IDs for an instance." } variable "tags" { type = map(string) - description = "The tags to add to the instance group." + description = "Tags to add to the instance group." } variable "enable_snp" { type = bool default = true - description = "Enable AMD SEV SNP. Setting this to true sets the cpu-option AmdSevSnp to enable." + description = "Enable AMD SEV-SNP for the instances." } variable "zone" { diff --git a/terraform/infrastructure/aws/modules/jump_host/main.tf b/terraform/infrastructure/aws/modules/jump_host/main.tf index ab9177e45..492493a01 100644 --- a/terraform/infrastructure/aws/modules/jump_host/main.tf +++ b/terraform/infrastructure/aws/modules/jump_host/main.tf @@ -7,7 +7,6 @@ terraform { } } - data "aws_ami" "ubuntu" { most_recent = true owners = ["099720109477"] # Canonical @@ -55,5 +54,4 @@ iptables -t nat -A PREROUTING -p tcp --dport ${port} -j DNAT --to-destination $$ iptables -t nat -A POSTROUTING -p tcp -d $${lb_ip} --dport ${port} -j SNAT --to-source $${internal_ip} %{endfor~} EOF - } diff --git a/terraform/infrastructure/aws/modules/jump_host/output.tf b/terraform/infrastructure/aws/modules/jump_host/output.tf index 7151bc0d4..1f604906b 100644 --- a/terraform/infrastructure/aws/modules/jump_host/output.tf +++ b/terraform/infrastructure/aws/modules/jump_host/output.tf @@ -1,3 +1,4 @@ output "ip" { - value = aws_instance.jump_host.public_ip + value = aws_instance.jump_host.public_ip + description = "Public IP of the jump host." } diff --git a/terraform/infrastructure/aws/modules/jump_host/variables.tf b/terraform/infrastructure/aws/modules/jump_host/variables.tf index b050b887b..ee8ffafa0 100644 --- a/terraform/infrastructure/aws/modules/jump_host/variables.tf +++ b/terraform/infrastructure/aws/modules/jump_host/variables.tf @@ -1,28 +1,28 @@ variable "base_name" { - description = "Base name of the jump host" - type = string -} - -variable "subnet_id" { - description = "Subnet ID to deploy the jump host into" - type = string -} - -variable "lb_internal_ip" { - description = "Internal IP of the load balancer" - type = string -} - -variable "iam_instance_profile" { - description = "IAM instance profile to attach to the jump host" + description = "Base name of the jump host." type = string } variable "ports" { - description = "Ports to forward to the load balancer" + description = "Ports to forward to the load balancer." type = list(number) } +variable "subnet_id" { + description = "Subnet ID to deploy the jump host into." + type = string +} + +variable "lb_internal_ip" { + description = "Internal IP of the load balancer." + type = string +} + +variable "iam_instance_profile" { + description = "IAM instance profile to attach to the jump host." + type = string +} + variable "security_groups" { type = list(string) description = "List of IDs of the security groups for an instance." diff --git a/terraform/infrastructure/aws/modules/load_balancer_target/main.tf b/terraform/infrastructure/aws/modules/load_balancer_target/main.tf index 3139cc980..952136325 100644 --- a/terraform/infrastructure/aws/modules/load_balancer_target/main.tf +++ b/terraform/infrastructure/aws/modules/load_balancer_target/main.tf @@ -8,7 +8,7 @@ terraform { } resource "aws_lb_target_group" "front_end" { - name = var.name + name = var.base_name port = var.port protocol = "TCP" vpc_id = var.vpc_id diff --git a/terraform/infrastructure/aws/modules/load_balancer_target/output.tf b/terraform/infrastructure/aws/modules/load_balancer_target/output.tf index 358781ef3..39e8860de 100644 --- a/terraform/infrastructure/aws/modules/load_balancer_target/output.tf +++ b/terraform/infrastructure/aws/modules/load_balancer_target/output.tf @@ -1,3 +1,4 @@ output "target_group_arn" { - value = aws_lb_target_group.front_end.arn + value = aws_lb_target_group.front_end.arn + description = "ARN of the load balancer target group." } diff --git a/terraform/infrastructure/aws/modules/load_balancer_target/variables.tf b/terraform/infrastructure/aws/modules/load_balancer_target/variables.tf index dc9b15770..e00146807 100644 --- a/terraform/infrastructure/aws/modules/load_balancer_target/variables.tf +++ b/terraform/infrastructure/aws/modules/load_balancer_target/variables.tf @@ -1,6 +1,6 @@ -variable "name" { +variable "base_name" { type = string - description = "Name of the load balancer target." + description = "Base name of the load balancer target." } variable "port" { @@ -32,5 +32,5 @@ variable "healthcheck_path" { variable "tags" { type = map(string) - description = "The tags to add to the loadbalancer." + description = "Tags to add to the loadbalancer." } diff --git a/terraform/infrastructure/aws/modules/public_private_subnet/output.tf b/terraform/infrastructure/aws/modules/public_private_subnet/output.tf index eda7d64cf..132fcfc23 100644 --- a/terraform/infrastructure/aws/modules/public_private_subnet/output.tf +++ b/terraform/infrastructure/aws/modules/public_private_subnet/output.tf @@ -3,6 +3,7 @@ output "private_subnet_id" { for az in data.aws_availability_zone.all : az.name => aws_subnet.private[az.name].id } + description = "Map of availability zones to private subnet id." } output "public_subnet_id" { diff --git a/terraform/infrastructure/aws/modules/public_private_subnet/variables.tf b/terraform/infrastructure/aws/modules/public_private_subnet/variables.tf index 0cbe58124..c549ef692 100644 --- a/terraform/infrastructure/aws/modules/public_private_subnet/variables.tf +++ b/terraform/infrastructure/aws/modules/public_private_subnet/variables.tf @@ -1,6 +1,6 @@ variable "name" { type = string - description = "Name of your Constellation, which is used as a prefix for tags." + description = "Name of the Constellation cluster." } variable "vpc_id" { @@ -30,5 +30,5 @@ variable "cidr_vpc_subnet_internet" { variable "tags" { type = map(string) - description = "The tags to add to the resource." + description = "Tags to add to the resource." } diff --git a/terraform/infrastructure/aws/outputs.tf b/terraform/infrastructure/aws/outputs.tf index 49ac8d817..62f220619 100644 --- a/terraform/infrastructure/aws/outputs.tf +++ b/terraform/infrastructure/aws/outputs.tf @@ -1,10 +1,15 @@ +# Outputs common to all CSPs + output "out_of_cluster_endpoint" { - value = local.out_of_cluster_endpoint + value = local.out_of_cluster_endpoint + description = "External endpoint for the Kubernetes API server. Only varies from the `in_cluster_endpoint` when using an internal load balancer." } output "in_cluster_endpoint" { - value = local.in_cluster_endpoint + value = local.in_cluster_endpoint + description = "Internal endpoint for the Kubernetes API server." } + output "api_server_cert_sans" { value = sort( distinct( @@ -17,21 +22,26 @@ output "api_server_cert_sans" { ) ) ) + description = "List of additional Subject Alternative Names (SANs) for the API server certificate." } output "uid" { - value = local.uid + value = local.uid + description = "Unique Identifier (UID) of the cluster." } -output "initSecret" { - value = random_password.initSecret.result - sensitive = true +output "init_secret" { + value = random_password.init_secret.result + sensitive = true + description = "Initialization secret to authenticate the bootstrapping node." } output "name" { - value = local.name + value = local.name + description = "Unique name of the Constellation cluster, comprised by name and UID." } -output "ip_cidr_nodes" { - value = local.cidr_vpc_subnet_nodes +output "ip_cidr_node" { + value = local.cidr_vpc_subnet_nodes + description = "CIDR block of the node network." } diff --git a/terraform/infrastructure/aws/variables.tf b/terraform/infrastructure/aws/variables.tf index b554c601e..6e7812f82 100644 --- a/terraform/infrastructure/aws/variables.tf +++ b/terraform/infrastructure/aws/variables.tf @@ -1,13 +1,15 @@ +# Variables common to all CSPs + variable "name" { type = string - description = "Name of your Constellation" + description = "Name of the Constellation cluster." validation { condition = length(var.name) <= 10 - error_message = "The length of the name of the Constellation must be <= 10 characters" + error_message = "The length of the name of the Constellation must be <= 10 characters." } validation { condition = var.name == lower(var.name) - error_message = "The name of the Constellation must be in lowercase" + error_message = "The name of the Constellation must be in lowercase." } } @@ -27,39 +29,53 @@ variable "node_groups" { } } -variable "iam_instance_profile_worker_nodes" { +variable "image_id" { type = string - description = "Name of the IAM instance profile for worker nodes" -} - -variable "iam_instance_profile_control_plane" { - type = string - description = "Name of the IAM instance profile for control plane nodes" -} - -variable "ami" { - type = string - description = "AMI ID" + description = "Amazon Machine Image (AMI) ID for the cluster's nodes." validation { - condition = length(var.ami) > 4 && substr(var.ami, 0, 4) == "ami-" - error_message = "The image_id value must be a valid AMI id, starting with \"ami-\"." + condition = length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-" + error_message = "The \"image_id\" value must be a valid AMI ID, starting with \"ami-\"." } } -variable "region" { - type = string - description = "The AWS region to create the cluster in" -} - -variable "zone" { - type = string - description = "The AWS availability zone name to create the cluster in" -} - variable "debug" { type = bool default = false - description = "Enable debug mode. This opens up a debugd port that can be used to deploy a custom bootstrapper." + description = "DO NOT USE IN PRODUCTION. Enable debug mode. This opens up a debugd port that can be used to deploy a custom bootstrapper." +} + +variable "custom_endpoint" { + type = string + default = "" + description = "Custom endpoint to use for the Kubernetes API server. If not set, the default endpoint will be used." +} + +variable "internal_load_balancer" { + type = bool + default = false + description = "Whether to use an internal load balancer for the cluster." +} + +# AWS-specific variables + +variable "iam_instance_profile_name_worker_nodes" { + type = string + description = "Name of the IAM instance profile for worker nodes." +} + +variable "iam_instance_profile_name_control_plane" { + type = string + description = "Name of the IAM instance profile for control plane nodes." +} + +variable "region" { + type = string + description = "AWS region to create the cluster in." +} + +variable "zone" { + type = string + description = "AWS availability zone name to create the cluster in." } variable "enable_snp" { @@ -67,15 +83,3 @@ variable "enable_snp" { default = true description = "Enable AMD SEV SNP. Setting this to true sets the cpu-option AmdSevSnp to enable." } - -variable "custom_endpoint" { - type = string - default = "" - description = "Custom endpoint to use for the Kubernetes apiserver. If not set, the default endpoint will be used." -} - -variable "internal_load_balancer" { - type = bool - default = false - description = "Use an internal load balancer." -} diff --git a/terraform/infrastructure/azure/main.tf b/terraform/infrastructure/azure/main.tf index b86e6ea48..fd72ce836 100644 --- a/terraform/infrastructure/azure/main.tf +++ b/terraform/infrastructure/azure/main.tf @@ -20,9 +20,9 @@ provider "azurerm" { } locals { - uid = random_id.uid.hex - name = "${var.name}-${local.uid}" - initSecretHash = random_password.initSecret.bcrypt_hash + uid = random_id.uid.hex + name = "${var.name}-${local.uid}" + init_secret_hash = random_password.init_secret.bcrypt_hash tags = { constellation-uid = local.uid, } @@ -54,7 +54,7 @@ resource "random_id" "uid" { byte_length = 4 } -resource "random_password" "initSecret" { +resource "random_password" "init_secret" { length = 32 special = true override_special = "_%@" @@ -245,7 +245,7 @@ module "scale_set_group" { zones = each.value.zones tags = merge( local.tags, - { constellation-init-secret-hash = local.initSecretHash }, + { constellation-init-secret-hash = local.init_secret_hash }, { constellation-maa-url = var.create_maa ? azurerm_attestation_provider.attestation_provider[0].attestation_uri : "" }, ) diff --git a/terraform/infrastructure/azure/modules/jump_host/outputs.tf b/terraform/infrastructure/azure/modules/jump_host/outputs.tf index fd341ca13..a83948ddb 100644 --- a/terraform/infrastructure/azure/modules/jump_host/outputs.tf +++ b/terraform/infrastructure/azure/modules/jump_host/outputs.tf @@ -1,3 +1,4 @@ output "ip" { - value = azurerm_linux_virtual_machine.jump_host.public_ip_address + value = azurerm_linux_virtual_machine.jump_host.public_ip_address + description = "Public IP of the jump host." } diff --git a/terraform/infrastructure/azure/modules/jump_host/variables.tf b/terraform/infrastructure/azure/modules/jump_host/variables.tf index 4811cbd0f..55f363a54 100644 --- a/terraform/infrastructure/azure/modules/jump_host/variables.tf +++ b/terraform/infrastructure/azure/modules/jump_host/variables.tf @@ -1,29 +1,29 @@ variable "base_name" { - description = "Base name of the jump host" + description = "Base name of the jump host." type = string } variable "ports" { - description = "Ports to forward to the load balancer" + description = "Ports to forward to the load balancer." type = list(number) } -variable "resource_group" { - description = "Resource group name to deploy the jump host into" - type = string -} - -variable "location" { - description = "Location to deploy the jump host into" - type = string -} - variable "subnet_id" { - description = "Subnet ID to deploy the jump host into" + description = "Subnet ID to deploy the jump host into." type = string } variable "lb_internal_ip" { - description = "Internal IP of the load balancer" + description = "Internal IP of the load balancer." + type = string +} + +variable "resource_group" { + description = "Resource group name to deploy the jump host into." + type = string +} + +variable "location" { + description = "Location to deploy the jump host into." type = string } diff --git a/terraform/infrastructure/azure/modules/load_balancer_backend/outputs.tf b/terraform/infrastructure/azure/modules/load_balancer_backend/outputs.tf index 70d283326..6001e05bc 100644 --- a/terraform/infrastructure/azure/modules/load_balancer_backend/outputs.tf +++ b/terraform/infrastructure/azure/modules/load_balancer_backend/outputs.tf @@ -1,4 +1,4 @@ output "backendpool_id" { value = azurerm_lb_backend_address_pool.backend_pool.id - description = "The ID of the created backend pool." + description = "ID of the created backend address pool." } diff --git a/terraform/infrastructure/azure/modules/load_balancer_backend/variables.tf b/terraform/infrastructure/azure/modules/load_balancer_backend/variables.tf index 93512df8f..aa1128366 100644 --- a/terraform/infrastructure/azure/modules/load_balancer_backend/variables.tf +++ b/terraform/infrastructure/azure/modules/load_balancer_backend/variables.tf @@ -1,17 +1,17 @@ variable "name" { type = string default = "constell" - description = "Base name of the cluster." + description = "Name of the Constellation cluster." } variable "frontend_ip_configuration_name" { type = string - description = "The name of the frontend IP configuration to use for the load balancer." + description = "Name of the frontend IP configuration to use for the load balancer." } variable "loadbalancer_id" { type = string - description = "The ID of the load balancer to add the backend to." + description = "ID of the load balancer to add the backend to." } variable "ports" { @@ -21,5 +21,5 @@ variable "ports" { health_check_protocol = string path = string })) - description = "The ports to add to the backend. Protocol can be either 'Tcp' or 'Https'. Path is only used for 'Https' protocol and can otherwise be null." + description = "Ports to add to the backend. Healtch check protocol can be either 'Tcp' or 'Https'. Path is only used for the 'Https' protocol and can otherwise be null." } diff --git a/terraform/infrastructure/azure/modules/scale_set/main.tf b/terraform/infrastructure/azure/modules/scale_set/main.tf index a90c0ac30..ad80ca43e 100644 --- a/terraform/infrastructure/azure/modules/scale_set/main.tf +++ b/terraform/infrastructure/azure/modules/scale_set/main.tf @@ -24,6 +24,7 @@ locals { resource "random_id" "uid" { byte_length = 4 } + resource "random_password" "password" { length = 16 min_lower = 1 @@ -92,7 +93,6 @@ resource "azurerm_linux_virtual_machine_scale_set" "scale_set" { } } - data_disk { storage_account_type = var.state_disk_type disk_size_gb = var.state_disk_size diff --git a/terraform/infrastructure/azure/modules/scale_set/variables.tf b/terraform/infrastructure/azure/modules/scale_set/variables.tf index 25d1d2da1..dd0f52ca5 100644 --- a/terraform/infrastructure/azure/modules/scale_set/variables.tf +++ b/terraform/infrastructure/azure/modules/scale_set/variables.tf @@ -1,6 +1,6 @@ variable "base_name" { type = string - description = "Base name of the instance group." + description = "Base name of the scale set." } variable "node_group_name" { @@ -10,7 +10,7 @@ variable "node_group_name" { variable "role" { type = string - description = "The role of the instance group." + description = "Role of the instance group." validation { condition = contains(["control-plane", "worker"], var.role) error_message = "The role has to be 'control-plane' or 'worker'." @@ -19,7 +19,7 @@ variable "role" { variable "tags" { type = map(string) - description = "Tags to include in the scale_set." + description = "Tags to include in the scale set." } variable "zones" { @@ -30,59 +30,59 @@ variable "zones" { variable "initial_count" { type = number - description = "The number of instances in this scale set." + description = "Number of instances in this scale set." } variable "instance_type" { type = string - description = "The Azure instance type to deploy." + description = "Azure instance type to deploy." } variable "state_disk_size" { type = number default = 30 - description = "The size of the state disk in GB." + description = "Disk size for the state disk of the nodes [GB]." } variable "resource_group" { type = string - description = "The name of the Azure resource group to create the Constellation cluster in." + description = "Name of the Azure resource group to create the Constellation cluster in." } variable "location" { type = string - description = "The Azure location to deploy the cluster in." + description = "Azure location to deploy the cluster in." } variable "image_id" { type = string - description = "The image to use for the cluster nodes." + description = "OS Image reference for the cluster's nodes." } variable "user_assigned_identity" { type = string - description = "The name of the user assigned identity to attache to the nodes of the cluster." + description = "Name of the user assigned identity to attache to the nodes of the cluster." } variable "state_disk_type" { type = string default = "Premium_LRS" - description = "The type of the state disk." + description = "Type of the state disk." } variable "network_security_group_id" { type = string - description = "The ID of the network security group to use for the scale set." + description = "ID of the network security group to use for the scale set." } variable "backend_address_pool_ids" { type = list(string) - description = "The IDs of the backend address pools to use for the scale set." + description = "IDs of the backend address pools to use for the scale set." } variable "subnet_id" { type = string - description = "The ID of the subnet to use for the scale set." + description = "ID of the subnet to use for the scale set." } variable "confidential_vm" { diff --git a/terraform/infrastructure/azure/outputs.tf b/terraform/infrastructure/azure/outputs.tf index 30f5bbc2b..945c793b8 100644 --- a/terraform/infrastructure/azure/outputs.tf +++ b/terraform/infrastructure/azure/outputs.tf @@ -1,9 +1,13 @@ +# Outputs common to all CSPs + output "out_of_cluster_endpoint" { - value = local.out_of_cluster_endpoint + value = local.out_of_cluster_endpoint + description = "External endpoint for the Kubernetes API server. Only varies from the `in_cluster_endpoint` when using an internal load balancer." } output "in_cluster_endpoint" { - value = local.in_cluster_endpoint + value = local.in_cluster_endpoint + description = "Internal endpoint for the Kubernetes API server." } output "api_server_cert_sans" { @@ -19,46 +23,58 @@ output "api_server_cert_sans" { ) ) ) + description = "List of Subject Alternative Names (SANs) for the API server certificate." } output "uid" { - value = local.uid + value = local.uid + description = "Unique Identifier (UID) of the cluster." } -output "initSecret" { - value = random_password.initSecret.result - sensitive = true -} - -output "attestationURL" { - value = var.create_maa ? azurerm_attestation_provider.attestation_provider[0].attestation_uri : "" -} - -output "network_security_group_name" { - value = azurerm_network_security_group.security_group.name -} - -output "loadbalancer_name" { - value = azurerm_lb.loadbalancer.name -} - - -output "user_assigned_identity_client_id" { - value = data.azurerm_user_assigned_identity.uaid.client_id -} - -output "resource_group" { - value = var.resource_group -} - -output "subscription_id" { - value = data.azurerm_subscription.current.subscription_id +output "init_secret" { + value = random_password.init_secret.result + sensitive = true + description = "Initialization secret to authenticate the bootstrapping node." } output "name" { - value = local.name + value = local.name + description = "Unique name of the Constellation cluster, comprised by name and UID." } -output "ip_cidr_nodes" { - value = local.cidr_vpc_subnet_nodes +output "ip_cidr_node" { + value = local.cidr_vpc_subnet_nodes + description = "CIDR block of the node network." +} + +# Azure-specific outputs + +output "attestation_url" { + value = var.create_maa ? azurerm_attestation_provider.attestation_provider[0].attestation_uri : "" + description = "URL of the cluster's Microsoft Azure Attestation (MAA) provider." +} + +output "network_security_group_name" { + value = azurerm_network_security_group.security_group.name + description = "Name of the cluster's network security group." +} + +output "loadbalancer_name" { + value = azurerm_lb.loadbalancer.name + description = "Name of the cluster's load balancer." +} + +output "user_assigned_identity_client_id" { + value = data.azurerm_user_assigned_identity.uaid.client_id + description = "Client ID of the user assigned identity used within the cluster." +} + +output "resource_group" { + value = var.resource_group + description = "Name of the resource group the cluster resides in." +} + +output "subscription_id" { + value = data.azurerm_subscription.current.subscription_id + description = "ID of the Azure subscription the cluster resides in." } diff --git a/terraform/infrastructure/azure/variables.tf b/terraform/infrastructure/azure/variables.tf index 32dcfcaa6..87786c71a 100644 --- a/terraform/infrastructure/azure/variables.tf +++ b/terraform/infrastructure/azure/variables.tf @@ -1,6 +1,8 @@ +# Variables common to all CSPs + variable "name" { type = string - description = "Base name of the cluster." + description = "Name of the Constellation cluster." } variable "node_groups" { @@ -19,26 +21,40 @@ variable "node_groups" { } } -variable "location" { - type = string - description = "The Azure location to deploy the cluster in." -} - variable "image_id" { type = string - description = "The image to use for the cluster nodes." -} - -variable "create_maa" { - type = bool - default = false - description = "Whether to create a Microsoft Azure attestation provider." + description = "OS image reference for the cluster's nodes." } variable "debug" { type = bool default = false - description = "Enable debug mode. This opens up a debugd port that can be used to deploy a custom bootstrapper." + description = "DO NOT USE IN PRODUCTION. Enable debug mode. This opens up a debugd port that can be used to deploy a custom bootstrapper." +} + +variable "custom_endpoint" { + type = string + default = "" + description = "Custom endpoint to use for the Kubernetes API server. If not set, the default endpoint will be used." +} + +variable "internal_load_balancer" { + type = bool + default = false + description = "Whether to use an internal load balancer for the cluster." +} + +# Azure-specific variables + +variable "location" { + type = string + description = "Azure location to deploy the cluster in." +} + +variable "create_maa" { + type = bool + default = false + description = "Whether to create a Microsoft Azure Attestation (MAA) provider." } variable "confidential_vm" { @@ -55,23 +71,12 @@ variable "secure_boot" { variable "resource_group" { type = string - description = "The name of the Azure resource group to create the Constellation cluster in." + description = "Name of the Azure resource group to create the cluster in." } + variable "user_assigned_identity" { type = string - description = "The name of the user assigned identity to attach to the nodes of the cluster. Should be of format: /subscriptions/$ID/resourceGroups/$RG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$NAME" -} - -variable "custom_endpoint" { - type = string - default = "" - description = "Custom endpoint to use for the Kubernetes apiserver. If not set, the default endpoint will be used." -} - -variable "internal_load_balancer" { - type = bool - default = false - description = "Whether to use an internal load balancer for the Constellation." + description = "Name of the user assigned identity to attach to the nodes of the cluster. Should be of format: /subscriptions/$ID/resourceGroups/$RG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$NAME" } variable "marketplace_image" { @@ -82,5 +87,5 @@ variable "marketplace_image" { version = string }) default = null - description = "Marketplace image to use for the cluster nodes." + description = "Marketplace image for the cluster's nodes." } diff --git a/terraform/infrastructure/gcp/main.tf b/terraform/infrastructure/gcp/main.tf index 8077d94bb..f11221349 100644 --- a/terraform/infrastructure/gcp/main.tf +++ b/terraform/infrastructure/gcp/main.tf @@ -30,9 +30,9 @@ provider "google-beta" { } locals { - uid = random_id.uid.hex - name = "${var.name}-${local.uid}" - initSecretHash = random_password.initSecret.bcrypt_hash + uid = random_id.uid.hex + name = "${var.name}-${local.uid}" + init_secret_hash = random_password.init_secret.bcrypt_hash labels = { constellation-uid = local.uid, } @@ -55,7 +55,7 @@ locals { for name, node_group in var.node_groups : node_group.role => name... } control_plane_instance_groups = [ - for control_plane in local.node_groups_by_role["control-plane"] : module.instance_group[control_plane].instance_group + for control_plane in local.node_groups_by_role["control-plane"] : module.instance_group[control_plane].instance_group_url ] in_cluster_endpoint = var.internal_load_balancer ? google_compute_address.loadbalancer_ip_internal[0].address : google_compute_global_address.loadbalancer_ip[0].address out_of_cluster_endpoint = var.debug && var.internal_load_balancer ? module.jump_host[0].ip : local.in_cluster_endpoint @@ -65,7 +65,7 @@ resource "random_id" "uid" { byte_length = 4 } -resource "random_password" "initSecret" { +resource "random_password" "init_secret" { length = 32 special = true override_special = "_%@" @@ -187,7 +187,7 @@ module "instance_group" { debug = var.debug named_ports = each.value.role == "control-plane" ? local.control_plane_named_ports : [] labels = local.labels - init_secret_hash = local.initSecretHash + init_secret_hash = local.init_secret_hash custom_endpoint = var.custom_endpoint } diff --git a/terraform/infrastructure/gcp/modules/instance_group/outputs.tf b/terraform/infrastructure/gcp/modules/instance_group/outputs.tf index 66f793fb0..f93c4558e 100644 --- a/terraform/infrastructure/gcp/modules/instance_group/outputs.tf +++ b/terraform/infrastructure/gcp/modules/instance_group/outputs.tf @@ -1,3 +1,4 @@ -output "instance_group" { - value = google_compute_instance_group_manager.instance_group_manager.instance_group +output "instance_group_url" { + value = google_compute_instance_group_manager.instance_group_manager.instance_group + description = "Full URL of the instance group." } diff --git a/terraform/infrastructure/gcp/modules/instance_group/variables.tf b/terraform/infrastructure/gcp/modules/instance_group/variables.tf index 016347ffd..f4b9a7cdb 100644 --- a/terraform/infrastructure/gcp/modules/instance_group/variables.tf +++ b/terraform/infrastructure/gcp/modules/instance_group/variables.tf @@ -10,7 +10,7 @@ variable "node_group_name" { variable "role" { type = string - description = "The role of the instance group." + description = "Role of the instance group." validation { condition = contains(["control-plane", "worker"], var.role) error_message = "The role has to be 'control-plane' or 'worker'." @@ -19,7 +19,7 @@ variable "role" { variable "uid" { type = string - description = "UID of the cluster. This is used for tags." + description = "Unique Identifier (UID) of the cluster." } variable "labels" { @@ -35,22 +35,22 @@ variable "instance_type" { variable "initial_count" { type = number - description = "Number of instances in the instance group." + description = "Number of instances in the group." } variable "image_id" { type = string - description = "Image ID for the nodes." + description = "OS Image reference for the cluster's nodes." } variable "disk_size" { type = number - description = "Disk size for the nodes, in GB." + description = "Disk size for the state disk of the nodes [GB]." } variable "disk_type" { type = string - description = "Disk type for the nodes. Has to be 'pd-standard' or 'pd-ssd'." + description = "Disk type for the nodes. Has to be either 'pd-standard' or 'pd-ssd'." } variable "network" { @@ -65,12 +65,12 @@ variable "subnetwork" { variable "kube_env" { type = string - description = "Kubernetes env." + description = "Value of the \"kube-env\" metadata key." } variable "init_secret_hash" { type = string - description = "Hash of the init secret." + description = "BCrypt Hash of the initialization secret." } variable "named_ports" { @@ -82,7 +82,7 @@ variable "named_ports" { variable "debug" { type = bool default = false - description = "Enable debug mode. This will enable serial port access on the instances." + description = "DO NOT USE IN PRODUCTION. Enable debug mode. This opens up a debugd port that can be used to deploy a custom bootstrapper." } variable "alias_ip_range_name" { @@ -97,5 +97,5 @@ variable "zone" { variable "custom_endpoint" { type = string - description = "Custom endpoint to use for the Kubernetes apiserver. If not set, the default endpoint will be used." + description = "Custom endpoint to use for the Kubernetes API server. If not set, the default endpoint will be used." } diff --git a/terraform/infrastructure/gcp/modules/internal_load_balancer/variables.tf b/terraform/infrastructure/gcp/modules/internal_load_balancer/variables.tf index 4ba586426..aa8bc441e 100644 --- a/terraform/infrastructure/gcp/modules/internal_load_balancer/variables.tf +++ b/terraform/infrastructure/gcp/modules/internal_load_balancer/variables.tf @@ -5,22 +5,22 @@ variable "name" { variable "region" { type = string - description = "The region where the load balancer will be created." + description = "Region to create the load balancer in." } variable "network" { type = string - description = "The network to which all network resources will be attached." + description = "Network to which network resources will be attached." } variable "backend_subnet" { type = string - description = "The subnet to which all backend network resources will be attached." + description = "Subnet to which backend network resources will be attached." } variable "health_check" { type = string - description = "The type of the health check. 'HTTPS' or 'TCP'." + description = "Type of the health check. Can either be 'HTTPS' or 'TCP'." validation { condition = contains(["HTTPS", "TCP"], var.health_check) error_message = "Health check must be either 'HTTPS' or 'TCP'." @@ -29,22 +29,22 @@ variable "health_check" { variable "port" { type = string - description = "The port on which to listen for incoming traffic." + description = "Port to listen on for incoming traffic." } variable "backend_port_name" { type = string - description = "Name of backend port. The same name should appear in the instance groups referenced by this service." + description = "Name of the load balancer's backend port. The same name should appear in the instance groups referenced by this service." } variable "backend_instance_group" { type = string - description = "The URL of the instance group resource from which the load balancer will direct traffic." + description = "Full URL of the instance group resource from which the load balancer will direct traffic." } variable "ip_address" { type = string - description = "The IP address that this forwarding rule serves." + description = "IP address that this forwarding rule serves." } variable "frontend_labels" { diff --git a/terraform/infrastructure/gcp/modules/jump_host/main.tf b/terraform/infrastructure/gcp/modules/jump_host/main.tf index f8de3e92f..76af8ab89 100644 --- a/terraform/infrastructure/gcp/modules/jump_host/main.tf +++ b/terraform/infrastructure/gcp/modules/jump_host/main.tf @@ -12,7 +12,6 @@ terraform { } } - data "google_compute_image" "image_ubuntu" { family = "ubuntu-2204-lts" project = "ubuntu-os-cloud" @@ -47,7 +46,7 @@ resource "google_compute_instance" "vm_instance" { metadata_startup_script = < 0 error_message = "constellation_kernel must be set if constellation_boot_mode is 'direct-linux-boot'" } + description = "Validation placeholder. Do not consume as output." } output "validate_constellation_initrd" { @@ -33,6 +53,7 @@ output "validate_constellation_initrd" { condition = var.constellation_boot_mode != "direct-linux-boot" || length(var.constellation_initrd) > 0 error_message = "constellation_initrd must be set if constellation_boot_mode is 'direct-linux-boot'" } + description = "Validation placeholder. Do not consume as output." } output "validate_constellation_cmdline" { @@ -41,12 +62,5 @@ output "validate_constellation_cmdline" { condition = var.constellation_boot_mode != "direct-linux-boot" || length(var.constellation_cmdline) > 0 error_message = "constellation_cmdline must be set if constellation_boot_mode is 'direct-linux-boot'" } -} - -output "name" { - value = "${var.name}-qemu" // placeholder, as per "uid" output -} - -output "ip_cidr_nodes" { - value = local.cidr_vpc_subnet_nodes + description = "Validation placeholder. Do not consume as output." } diff --git a/terraform/infrastructure/qemu/variables.tf b/terraform/infrastructure/qemu/variables.tf index bd5b79afa..83483b859 100644 --- a/terraform/infrastructure/qemu/variables.tf +++ b/terraform/infrastructure/qemu/variables.tf @@ -1,3 +1,11 @@ +# Variables common to all CSPs + +variable "name" { + type = string + default = "constellation" + description = "Name of the Constellation cluster." +} + variable "node_groups" { type = map(object({ role = string @@ -14,91 +22,88 @@ variable "node_groups" { description = "A map of node group names to node group configurations." } +variable "image_id" { + type = string + description = "Path to the OS image for the cluster's nodes." +} + +variable "custom_endpoint" { + type = string + default = "" + description = "Custom endpoint to use for the Kubernetes API server. If not set, the default endpoint will be used." +} + +# QEMU-specific variables + variable "machine" { type = string default = "q35" - description = "machine type. use 'q35' for secure boot and 'pc' for non secure boot. See 'qemu-system-x86_64 -machine help'" + description = "Machine type. Use 'q35' for secure boot and 'pc' for non secure boot. See 'qemu-system-x86_64 -machine help'." } variable "libvirt_uri" { type = string - description = "libvirt socket uri" + description = "URI of the Libvirt socket." } variable "constellation_boot_mode" { type = string - description = "constellation boot mode. Can be 'uefi' or 'direct-linux-boot'" + description = "Constellation boot mode. Can be 'uefi' or 'direct-linux-boot'." validation { condition = anytrue([ var.constellation_boot_mode == "uefi", var.constellation_boot_mode == "direct-linux-boot", ]) - error_message = "constellation_boot_mode must be 'uefi' or 'direct-linux-boot'" + error_message = "constellation_boot_mode must be 'uefi' or 'direct-linux-boot'." } } -variable "constellation_os_image" { - type = string - description = "constellation OS file path" -} - variable "constellation_kernel" { type = string - description = "constellation Kernel file path" + description = "Constellation Kernel file path." default = "" } variable "constellation_initrd" { type = string - description = "constellation initrd file path" + description = "Constellation initrd file path." default = "" } variable "constellation_cmdline" { type = string - description = "constellation kernel cmdline" + description = "Constellation kernel cmdline." default = "" } variable "image_format" { type = string default = "qcow2" - description = "image format" + description = "Image format." } + variable "firmware" { type = string default = "/usr/share/OVMF/OVMF_CODE.fd" - description = "path to UEFI firmware file. Use \"OVMF_CODE_4M.ms.fd\" on Ubuntu and \"OVMF_CODE.fd\" or \"OVMF_CODE.secboot.fd\" on Fedora." + description = "Path to UEFI firmware file. Use \"OVMF_CODE_4M.ms.fd\" on Ubuntu and \"OVMF_CODE.fd\" or \"OVMF_CODE.secboot.fd\" on Fedora." } variable "nvram" { type = string - description = "path to UEFI NVRAM template file. Used for secure boot." + description = "Path to UEFI NVRAM template file. Used for secure boot." } variable "metadata_api_image" { type = string - description = "container image of the QEMU metadata api server" + description = "Container image of the QEMU metadata API server." } variable "metadata_libvirt_uri" { type = string - description = "libvirt uri for the metadata api server" + description = "Libvirt URI for the metadata API server." } variable "libvirt_socket_path" { type = string - description = "path to libvirt socket in case of unix socket" -} - -variable "name" { - type = string - default = "constellation" - description = "name prefix of the cluster VMs" -} - -variable "custom_endpoint" { - type = string - default = "" - description = "Custom endpoint to use for the Kubernetes apiserver. If not set, the default endpoint will be used." + description = "Path to Libvirt socket in case of unix socket." } diff --git a/terraform/legacy-module/aws-constellation/main.tf b/terraform/legacy-module/aws-constellation/main.tf index bc6aa2a9c..de89f7a68 100644 --- a/terraform/legacy-module/aws-constellation/main.tf +++ b/terraform/legacy-module/aws-constellation/main.tf @@ -29,17 +29,17 @@ module "fetch_image" { } module "aws" { - source = "../../infrastructure/aws" - name = var.name - node_groups = var.node_groups - iam_instance_profile_worker_nodes = module.aws_iam.worker_nodes_instance_profile - iam_instance_profile_control_plane = module.aws_iam.control_plane_instance_profile - ami = module.fetch_image.image - region = local.region - zone = var.zone - debug = var.debug - enable_snp = var.enable_snp - custom_endpoint = var.custom_endpoint + source = "../../infrastructure/aws" + name = var.name + node_groups = var.node_groups + iam_instance_profile_name_worker_nodes = module.aws_iam.iam_instance_profile_name_worker_nodes + iam_instance_profile_name_control_plane = module.aws_iam.iam_instance_profile_name_control_plane + image_id = module.fetch_image.image + region = local.region + zone = var.zone + debug = var.debug + enable_snp = var.enable_snp + custom_endpoint = var.custom_endpoint } module "constellation" { @@ -53,15 +53,15 @@ module "constellation" { uid = module.aws.uid clusterEndpoint = module.aws.out_of_cluster_endpoint inClusterEndpoint = module.aws.in_cluster_endpoint - initSecretHash = module.aws.initSecret - ipCidrNode = module.aws.ip_cidr_nodes + initSecretHash = module.aws.init_secret + ipCidrNode = module.aws.ip_cidr_node apiServerCertSANs = module.aws.api_server_cert_sans node_groups = var.node_groups aws_config = { - region = local.region - zone = var.zone - iam_instance_profile_worker_nodes = module.aws_iam.worker_nodes_instance_profile - iam_instance_profile_control_plane = module.aws_iam.control_plane_instance_profile + region = local.region + zone = var.zone + iam_instance_profile_name_worker_nodes = module.aws_iam.iam_instance_profile_name_worker_nodes + iam_instance_profile_name_control_plane = module.aws_iam.iam_instance_profile_name_control_plane } depends_on = [module.aws, null_resource.ensure_yq] } diff --git a/terraform/legacy-module/azure-constellation/main.tf b/terraform/legacy-module/azure-constellation/main.tf index 5bfb74386..8161bbeab 100644 --- a/terraform/legacy-module/azure-constellation/main.tf +++ b/terraform/legacy-module/azure-constellation/main.tf @@ -19,7 +19,7 @@ module "fetch_image" { module "azure_iam" { source = "../../infrastructure/iam/azure" - region = var.location + location = var.location service_principal_name = var.service_principal_name resource_group_name = var.resource_group_name } @@ -47,8 +47,8 @@ module "constellation" { uid = module.azure.uid clusterEndpoint = module.azure.out_of_cluster_endpoint inClusterEndpoint = module.azure.in_cluster_endpoint - initSecretHash = module.azure.initSecret - ipCidrNode = module.azure.ip_cidr_nodes + initSecretHash = module.azure.init_secret + ipCidrNode = module.azure.ip_cidr_node apiServerCertSANs = module.azure.api_server_cert_sans node_groups = var.node_groups azure_config = { @@ -59,7 +59,7 @@ module "constellation" { userAssignedIdentity = module.azure_iam.uami_id deployCSIDriver = var.deploy_csi_driver secureBoot = var.secure_boot - maaURL = module.azure.attestationURL + maaURL = module.azure.attestation_url networkSecurityGroupName = module.azure.network_security_group_name loadBalancerName = module.azure.loadbalancer_name } diff --git a/terraform/legacy-module/constellation-cluster/main.tf b/terraform/legacy-module/constellation-cluster/main.tf index 9c4223b25..f84406f16 100644 --- a/terraform/legacy-module/constellation-cluster/main.tf +++ b/terraform/legacy-module/constellation-cluster/main.tf @@ -41,8 +41,8 @@ resource "null_resource" "aws_config" { command = <