diff --git a/.gitlab/README.md.template b/.gitlab/README.md.template index 1793fc300ff920a4c9dbd03ab93595d710423def..5c9e3a156270960dac68b09d5fe238d7c3b644e5 100644 --- a/.gitlab/README.md.template +++ b/.gitlab/README.md.template @@ -199,6 +199,60 @@ include: stages: [validate, build, deploy] ``` +### Configure `id_tokens` + +> [!note] +> Due to [lacking support](https://gitlab.com/gitlab-org/gitlab/-/issues/452451) +> of map nodes as input value types the configuration for `id_tokens` is somewhat special, +> but nonetheless super easy. Read along! + +To configure [`id_tokens`](https://docs.gitlab.com/ci/yaml/#id_tokens) support you need these +three things: + +1. set the `enable_id_tokens` input to `true`. +2. configure the `.gitlab-tofu:id_tokens` job with your desired `id_tokens` setup. +3. (optionally) provide the `.gitlab/ci/setup-id-tokens.sh` script to configure things, + like assuming IAM roles. + +An example setup may look like this: + +```yaml +include: + - component: $CI_SERVER_FQDN/components/opentofu/validate-plan-apply@<VERSION> + inputs: + # The version must currently be specified explicitly as an input, + # to find the correctly associated images. # This can be removed + # once https://gitlab.com/gitlab-org/gitlab/-/issues/438275 is solved. + version: <VERSION> # component version + opentofu_version: <OPENTOFU_VERSION> + enable_id_tokens: true + +stages: [validate, build, deploy] + +.gitlab-tofu:id_tokens: + id_tokens: + GITLAB_OIDC_TOKEN: + aud: https://gitlab.com +``` + +Then in the `.gitlab/ci/setup-id-tokens.sh` script you might assume a AWS IAM role: + +```shell +apk add --no-cache aws-cli +export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" \ + $(aws sts assume-role-with-web-identity \ + --role-arn ${GITLAB_CI_ROLE_ARN} \ + --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}" \ + --web-identity-token ${GITLAB_OIDC_TOKEN} \ + --duration-seconds 3600 \ + --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \ + --output text)) +aws sts get-caller-identity +``` + +You might configure the name of the `id_tokens` job and the setup script location +with the `id_tokens_base_job_name` and `id_tokens_setup_script` inputs, respectively. + ### Access to Terraform Module Registry Similar to automatically configuring the [GitLab-managed Terraform state backend] diff --git a/.gitlab/scripts/update-opentofu-versions.sh b/.gitlab/scripts/update-opentofu-versions.sh index bfd54706701a5ddda38957fb1bdb8007e6e7bd6a..417a7a822b21a4b148cee16b300bedee816d6ec9 100755 --- a/.gitlab/scripts/update-opentofu-versions.sh +++ b/.gitlab/scripts/update-opentofu-versions.sh @@ -8,7 +8,7 @@ project_dir="$script_dir/../.." echo "Updating template files ..." templates="templates/*.yml" -templates_exclude="templates/delete-state.yml templates/module-release.yml" +templates_exclude="templates/delete-state.yml templates/module-release.yml templates/__internal_id_tokens_base_job.yml" for relative_template_file in $templates; do if echo "$templates_exclude" | grep -q "$relative_template_file"; then continue; fi diff --git a/README.md b/README.md index 6c89664dce8d911c6b8acc805485565dd4c7fc8e..4f490c5065775ebde64263861b3436519a502f43 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,60 @@ include: stages: [validate, build, deploy] ``` +### Configure `id_tokens` + +> [!note] +> Due to [lacking support](https://gitlab.com/gitlab-org/gitlab/-/issues/452451) +> of map nodes as input value types the configuration for `id_tokens` is somewhat special, +> but nonetheless super easy. Read along! + +To configure [`id_tokens`](https://docs.gitlab.com/ci/yaml/#id_tokens) support you need these +three things: + +1. set the `enable_id_tokens` input to `true`. +2. configure the `.gitlab-tofu:id_tokens` job with your desired `id_tokens` setup. +3. (optionally) provide the `.gitlab/ci/setup-id-tokens.sh` script to configure things, + like assuming IAM roles. + +An example setup may look like this: + +```yaml +include: + - component: $CI_SERVER_FQDN/components/opentofu/validate-plan-apply@<VERSION> + inputs: + # The version must currently be specified explicitly as an input, + # to find the correctly associated images. # This can be removed + # once https://gitlab.com/gitlab-org/gitlab/-/issues/438275 is solved. + version: <VERSION> # component version + opentofu_version: <OPENTOFU_VERSION> + enable_id_tokens: true + +stages: [validate, build, deploy] + +.gitlab-tofu:id_tokens: + id_tokens: + GITLAB_OIDC_TOKEN: + aud: https://gitlab.com +``` + +Then in the `.gitlab/ci/setup-id-tokens.sh` script you might assume a AWS IAM role: + +```shell +apk add --no-cache aws-cli +export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" \ + $(aws sts assume-role-with-web-identity \ + --role-arn ${GITLAB_CI_ROLE_ARN} \ + --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}" \ + --web-identity-token ${GITLAB_OIDC_TOKEN} \ + --duration-seconds 3600 \ + --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \ + --output text)) +aws sts get-caller-identity +``` + +You might configure the name of the `id_tokens` job and the setup script location +with the `id_tokens_base_job_name` and `id_tokens_setup_script` inputs, respectively. + ### Access to Terraform Module Registry Similar to automatically configuring the [GitLab-managed Terraform state backend] diff --git a/templates/__internal_id_tokens_base_job.yml b/templates/__internal_id_tokens_base_job.yml new file mode 100644 index 0000000000000000000000000000000000000000..8775b65b7ce82228e2a16b3f77d1e541d4f5cbed --- /dev/null +++ b/templates/__internal_id_tokens_base_job.yml @@ -0,0 +1,21 @@ +spec: + inputs: + # NOTE: see the using templates for their description + as: {type: string} + id_tokens_base_job_name: {type: string} + id_tokens_setup_script: {type: string} + +--- + + +# NOTE: okay, this is bad, but it's what we got. +# We have to outsource this job (see the using templates for why we have it in the first place) +# because GitLab ALWAYS evaluates jobs, even if they are never used. +# This implies that all base jobs have to exist. +# And the only way for GitLab NOT to parse a job is to NOT include it. +# Thus, we simply do not include this if we don't have to. +'.$[[ inputs.as ]]:id_tokens-setup:true': + extends: $[[ inputs.id_tokens_base_job_name ]] + before_script: + - test -f "$[[ inputs.id_tokens_setup_script ]]" && . $[[ inputs.id_tokens_setup_script ]] + diff --git a/templates/apply.yml b/templates/apply.yml index be1c76c3c087615a4f109cfd8e4fb92ea35d50a9..2539887f50a2a34790eadd37bf868c2919e4b0ca 100644 --- a/templates/apply.yml +++ b/templates/apply.yml @@ -99,10 +99,49 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the job. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend this job from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- +include: + # NOTE: see the note in that template file for what he heck is going on here. + - local: '/templates/__internal_id_tokens_base_job.yml' + rules: + - if: '"$[[ inputs.enable_id_tokens ]]" == "true"' + inputs: + as: $[[ inputs.as ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] + +# NOTE: due to the lacking support of providing map nodes as input values +# we need to hack support for id_tokens together. It's even worse that id_tokens +# do NOT have a consistent type - or rather it's child nodes - for example, the `aud` +# can be a literal string value, a variable or an array. Limitations, bear with me. +# See https://gitlab.com/gitlab-org/gitlab/-/issues/452451 +'.$[[ inputs.as ]]:id_tokens-setup:false': + extends: null + '$[[ inputs.as ]]': + extends: + # NOTE: see the comment above. This is to support the `id_tokens` setup. + - '.$[[ inputs.as ]]:id_tokens-setup:$[[ inputs.enable_id_tokens ]]' stage: $[[ inputs.stage ]] environment: name: $GITLAB_TOFU_STATE_NAME diff --git a/templates/destroy.yml b/templates/destroy.yml index 45e0997b9e744634972d09500bb049cefbc8a6d9..f70df31914648f6d7666fbe043c408ababf7ac87 100644 --- a/templates/destroy.yml +++ b/templates/destroy.yml @@ -103,10 +103,49 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the job. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend this job from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- +include: + # NOTE: see the note in that template file for what he heck is going on here. + - local: '/templates/__internal_id_tokens_base_job.yml' + rules: + - if: '"$[[ inputs.enable_id_tokens ]]" == "true"' + inputs: + as: $[[ inputs.as ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] + +# NOTE: due to the lacking support of providing map nodes as input values +# we need to hack support for id_tokens together. It's even worse that id_tokens +# do NOT have a consistent type - or rather it's child nodes - for example, the `aud` +# can be a literal string value, a variable or an array. Limitations, bear with me. +# See https://gitlab.com/gitlab-org/gitlab/-/issues/452451 +'.$[[ inputs.as ]]:id_tokens-setup:false': + extends: null + '$[[ inputs.as ]]': + extends: + # NOTE: see the comment above. This is to support the `id_tokens` setup. + - '.$[[ inputs.as ]]:id_tokens-setup:$[[ inputs.enable_id_tokens ]]' stage: $[[ inputs.stage ]] environment: name: $GITLAB_TOFU_STATE_NAME diff --git a/templates/full-pipeline.yml b/templates/full-pipeline.yml index 290e81bb2925a828d76275a7c2aa2b78ef390dfb..98403b142cd9a413082558b551db2d11bcaf83b8 100644 --- a/templates/full-pipeline.yml +++ b/templates/full-pipeline.yml @@ -202,6 +202,24 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the pipeline. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend the jobs from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- @@ -241,6 +259,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/test.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "true"' @@ -265,6 +286,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/plan.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -289,6 +313,9 @@ include: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/apply.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -310,6 +337,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/destroy.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -330,6 +360,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/delete-state.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -418,6 +451,9 @@ stages: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role_to_plan: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] trigger_in_child_pipeline: false forward: yaml_variables: true diff --git a/templates/graph.yml b/templates/graph.yml index c78cde0ae86b353bdd6d2a1719f1dd817cc31e6c..ed881e57b45f5d13a2347b1deef9accba82bec64 100644 --- a/templates/graph.yml +++ b/templates/graph.yml @@ -80,6 +80,13 @@ spec: default: [] type: array description: 'Defines the `needs` of the job.' + rules: + # FIXME: eventually, we'll want to define `null` as the default, + # but this is NOT support yet, see + # https://gitlab.com/gitlab-org/gitlab/-/issues/440468 + default: [{when: on_success}] + type: array + description: 'Defines the `rules` of the job.' cache_policy: default: pull-push type: string @@ -100,12 +107,52 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the job. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend this job from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- +include: + # NOTE: see the note in that template file for what he heck is going on here. + - local: '/templates/__internal_id_tokens_base_job.yml' + rules: + - if: '"$[[ inputs.enable_id_tokens ]]" == "true"' + inputs: + as: $[[ inputs.as ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] + +# NOTE: due to the lacking support of providing map nodes as input values +# we need to hack support for id_tokens together. It's even worse that id_tokens +# do NOT have a consistent type - or rather it's child nodes - for example, the `aud` +# can be a literal string value, a variable or an array. Limitations, bear with me. +# See https://gitlab.com/gitlab-org/gitlab/-/issues/452451 +'.$[[ inputs.as ]]:id_tokens-setup:false': + extends: null + '$[[ inputs.as ]]': + extends: + # NOTE: see the comment above. This is to support the `id_tokens` setup. + - '.$[[ inputs.as ]]:id_tokens-setup:$[[ inputs.enable_id_tokens ]]' stage: $[[ inputs.stage ]] needs: $[[ inputs.needs ]] + rules: $[[ inputs.rules ]] cache: key: "$__CACHE_KEY_HACK" policy: $[[ inputs.cache_policy ]] diff --git a/templates/job-templates.yml b/templates/job-templates.yml index eaa2d306161fccc811d3318729eef823ccab3066..6f69de66adb5eeb5e285aea6b8788cedb75c6eab 100644 --- a/templates/job-templates.yml +++ b/templates/job-templates.yml @@ -107,6 +107,24 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the pipeline. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend the jobs from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- @@ -139,6 +157,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/graph.yml' inputs: as: '$[[ inputs.job_name_prefix ]]graph' @@ -154,6 +175,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/test.yml' inputs: as: '$[[ inputs.job_name_prefix ]]test' @@ -171,6 +195,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/plan.yml' inputs: as: '$[[ inputs.job_name_prefix ]]plan' @@ -191,6 +218,9 @@ include: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/apply.yml' inputs: as: '$[[ inputs.job_name_prefix ]]apply' @@ -209,6 +239,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/destroy.yml' inputs: as: '$[[ inputs.job_name_prefix ]]destroy' @@ -227,6 +260,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/delete-state.yml' inputs: as: '$[[ inputs.job_name_prefix ]]delete-state' diff --git a/templates/plan.yml b/templates/plan.yml index 73b4a5118416234e0b2bfe08d384d34baeda9690..52b21866060213206455fabaaf5866f0bfde9f10 100644 --- a/templates/plan.yml +++ b/templates/plan.yml @@ -113,9 +113,37 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the job. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend this job from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- +include: + # NOTE: see the note in that template file for what he heck is going on here. + - local: '/templates/__internal_id_tokens_base_job.yml' + rules: + - if: '"$[[ inputs.enable_id_tokens ]]" == "true"' + inputs: + as: $[[ inputs.as ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] + # NOTE: the two following jobs are necessary to implement the abstraction logic # required for the `warning_on_non_empty_plan` input. # Without any kind of flow control support for the GitLab CI YAML we cannot infer @@ -142,11 +170,21 @@ spec: # but we still want to upload all the artifacts. when: always +# NOTE: due to the lacking support of providing map nodes as input values +# we need to hack support for id_tokens together. It's even worse that id_tokens +# do NOT have a consistent type - or rather it's child nodes - for example, the `aud` +# can be a literal string value, a variable or an array. Limitations, bear with me. +# See https://gitlab.com/gitlab-org/gitlab/-/issues/452451 +'.$[[ inputs.as ]]:id_tokens-setup:false': + extends: null + '$[[ inputs.as ]]': - stage: $[[ inputs.stage ]] extends: # NOTE: see the comment above. This is to support the `warning_on_non_empty_plan` input. - '.$[[ inputs.as ]]:detailed_exitcode:warning:$[[ inputs.warning_on_non_empty_plan ]]' + # NOTE: see the comment above. This is to support the `id_tokens` setup. + - '.$[[ inputs.as ]]:id_tokens-setup:$[[ inputs.enable_id_tokens ]]' + stage: $[[ inputs.stage ]] environment: name: $[[ inputs.state_name ]] action: prepare diff --git a/templates/test.yml b/templates/test.yml index a76e3293c24b73d6d05dc913cc4e1951152aa795..124ff3737ed84c24a6baf88081d20eced6ec946a 100644 --- a/templates/test.yml +++ b/templates/test.yml @@ -102,13 +102,52 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the job. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend this job from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- +include: + # NOTE: see the note in that template file for what he heck is going on here. + - local: '/templates/__internal_id_tokens_base_job.yml' + rules: + - if: '"$[[ inputs.enable_id_tokens ]]" == "true"' + inputs: + as: $[[ inputs.as ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] + +# NOTE: due to the lacking support of providing map nodes as input values +# we need to hack support for id_tokens together. It's even worse that id_tokens +# do NOT have a consistent type - or rather it's child nodes - for example, the `aud` +# can be a literal string value, a variable or an array. Limitations, bear with me. +# See https://gitlab.com/gitlab-org/gitlab/-/issues/452451 +'.$[[ inputs.as ]]:id_tokens-setup:false': + extends: null + '$[[ inputs.as ]]': stage: $[[ inputs.stage ]] needs: $[[ inputs.needs ]] rules: $[[ inputs.rules ]] + extends: + # NOTE: see the comment above. This is to support the `id_tokens` setup. + - '.$[[ inputs.as ]]:id_tokens-setup:$[[ inputs.enable_id_tokens ]]' cache: key: "$__CACHE_KEY_HACK" policy: $[[ inputs.cache_policy ]] diff --git a/templates/validate-plan-apply.yml b/templates/validate-plan-apply.yml index f1c50051c4fbb540644bcf1cbab08ec7602a38f6..f72f9c9af12413c91d345247b27bbeaef7a9e600 100644 --- a/templates/validate-plan-apply.yml +++ b/templates/validate-plan-apply.yml @@ -166,6 +166,24 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the pipeline. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend the jobs from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- @@ -206,6 +224,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/plan.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -231,6 +252,9 @@ include: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/apply.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -253,6 +277,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] # NOTE: the following configuration is only used if `trigger_in_child_pipeline` is enabled. @@ -311,6 +338,9 @@ stages: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role_to_plan: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] trigger_in_child_pipeline: false forward: yaml_variables: true diff --git a/templates/validate-plan-destroy.yml b/templates/validate-plan-destroy.yml index 1d303fd6eaef9113cd84dadbc85c78b7b7614f63..b21f69b94ca7d9526a46f59beac41ae59fca8ca2 100644 --- a/templates/validate-plan-destroy.yml +++ b/templates/validate-plan-destroy.yml @@ -172,6 +172,24 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the pipeline. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend the jobs from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- @@ -212,6 +230,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/plan.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -238,6 +259,9 @@ include: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/destroy.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -261,6 +285,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/delete-state.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -344,6 +371,9 @@ stages: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role_to_plan: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] trigger_in_child_pipeline: false forward: yaml_variables: true diff --git a/templates/validate-plan.yml b/templates/validate-plan.yml index ed976b6f333474f60bed15a95a26b4bcec0b4559..136e9d7107fce3b44473714264735c6af69e6432 100644 --- a/templates/validate-plan.yml +++ b/templates/validate-plan.yml @@ -150,6 +150,24 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the pipeline. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend the jobs from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- @@ -190,6 +208,9 @@ include: auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]] auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] - local: '/templates/plan.yml' rules: - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"' @@ -215,6 +236,9 @@ include: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] # NOTE: the following configuration is only used if `trigger_in_child_pipeline` is enabled. @@ -270,6 +294,9 @@ stages: auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]] allow_developer_role_to_plan: $[[ inputs.allow_developer_role_to_plan ]] auto_define_backend: $[[ inputs.auto_define_backend ]] + enable_id_tokens: $[[ inputs.enable_id_tokens ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] trigger_in_child_pipeline: false forward: yaml_variables: true diff --git a/templates/validate.yml b/templates/validate.yml index 14154a195b7b0b668e41a8ad6861c94f22c8d6e1..ef0a042005e26a961b2dda085ca99ac7c46019fa 100644 --- a/templates/validate.yml +++ b/templates/validate.yml @@ -99,10 +99,50 @@ spec: default: false type: boolean description: 'Whether to automatically define the HTTP backend configuration block.' - + enable_id_tokens: + default: false + type: boolean + description: | + Whether to enable `id_tokens` support for the job. + This works by extending a hidden base job configuration with the `id_tokens` field. + The job should only contain the `id_tokens` field, the rest may be overridden. + The job name can be configured with `id_tokens_base_job_name` if necessary. + If the script given in `id_tokens_setup_script` exists, it will be sourced so that setup actions can be performed, + like assuming an IAM role of your cloud provider. + id_tokens_base_job_name: + default: '.gitlab-tofu:id_tokens' + type: string + description: 'Name of the hidden base job containing the `id_tokens` configuration to extend this job from. Make sure to only configure `id_tokens`, everything else might be overridden.' + id_tokens_setup_script: + default: '.gitlab/ci/setup-id-tokens.sh' + type: string + description: 'Path to a shell script that is sourced when `enable_id_tokens` is `true`.' --- +include: + # NOTE: see the note in that template file for what he heck is going on here. + - local: '/templates/__internal_id_tokens_base_job.yml' + rules: + - if: '"$[[ inputs.enable_id_tokens ]]" == "true"' + inputs: + as: $[[ inputs.as ]] + id_tokens_base_job_name: $[[ inputs.id_tokens_base_job_name ]] + id_tokens_setup_script: $[[ inputs.id_tokens_setup_script ]] + +# NOTE: due to the lacking support of providing map nodes as input values +# we need to hack support for id_tokens together. It's even worse that id_tokens +# do NOT have a consistent type - or rather it's child nodes - for example, the `aud` +# can be a literal string value, a variable or an array. Limitations, bear with me. +# See https://gitlab.com/gitlab-org/gitlab/-/issues/452451 +# Oh and yes, it gets worse, the `true` counterpart for this job is in __internal_id_tokens_base_job.yml +# See the note there for why ... +'.$[[ inputs.as ]]:id_tokens-setup:false': + extends: null + '$[[ inputs.as ]]': + extends: + # NOTE: see the comment above. This is to support the `id_tokens` setup. + - '.$[[ inputs.as ]]:id_tokens-setup:$[[ inputs.enable_id_tokens ]]' stage: $[[ inputs.stage ]] rules: $[[ inputs.rules ]] cache: diff --git a/tests/iac-id-tokens/backend.tf b/tests/iac-id-tokens/backend.tf new file mode 100644 index 0000000000000000000000000000000000000000..1736bf13b6ce62319d00b07243000e4ffea76c3d --- /dev/null +++ b/tests/iac-id-tokens/backend.tf @@ -0,0 +1,3 @@ +terraform { + backend "http" {} +} diff --git a/tests/iac-id-tokens/id-tokens-setup.sh b/tests/iac-id-tokens/id-tokens-setup.sh new file mode 100644 index 0000000000000000000000000000000000000000..77f39597fbbed45de543ec582092561f52f4d93a --- /dev/null +++ b/tests/iac-id-tokens/id-tokens-setup.sh @@ -0,0 +1 @@ +touch id-tokens-setup-ran diff --git a/tests/iac-id-tokens/main.tf b/tests/iac-id-tokens/main.tf new file mode 100644 index 0000000000000000000000000000000000000000..aa8705c6f46153325b06b6113fdab94804fa7df4 --- /dev/null +++ b/tests/iac-id-tokens/main.tf @@ -0,0 +1,41 @@ +module "random_pet" { + source = "./modules/random-pet" +} + +resource "local_file" "foo" { + content = "foo!" + filename = "${path.module}/foo.bar" +} + +locals { + ts = plantimestamp() +} + +// NOTE: always force a change. +resource "null_resource" "this" { + triggers = { + timestamp = local.ts + } +} + +variable "ci_project_name" { + type = string + default = "default" +} + +variable "test_variable" { + type = string + default = "default value" +} + +output "project_name" { + value = var.ci_project_name +} + +output "test_variable" { + value = var.test_variable +} + +output "this_always_changes" { + value = local.ts +} diff --git a/tests/iac-id-tokens/modules/random-pet/main.tf b/tests/iac-id-tokens/modules/random-pet/main.tf new file mode 100644 index 0000000000000000000000000000000000000000..382c4e673853109279a8d53323b2aad80a8848e2 --- /dev/null +++ b/tests/iac-id-tokens/modules/random-pet/main.tf @@ -0,0 +1,12 @@ +terraform { + required_providers { + random = { + source = "hashicorp/random" + version = "3.1.2" + } + } +} + +resource "random_pet" "random_pet" { + length = var.length +} diff --git a/tests/iac-id-tokens/modules/random-pet/outputs.tf b/tests/iac-id-tokens/modules/random-pet/outputs.tf new file mode 100644 index 0000000000000000000000000000000000000000..6a771003bd661f665b2e89b1964e8d48dd6cd764 --- /dev/null +++ b/tests/iac-id-tokens/modules/random-pet/outputs.tf @@ -0,0 +1,3 @@ +output "random_pet" { + value = random_pet.random_pet.id +} diff --git a/tests/iac-id-tokens/modules/random-pet/variables.tf b/tests/iac-id-tokens/modules/random-pet/variables.tf new file mode 100644 index 0000000000000000000000000000000000000000..3e65d0a1e2d133e7616dee62a920cfadf46a1914 --- /dev/null +++ b/tests/iac-id-tokens/modules/random-pet/variables.tf @@ -0,0 +1,4 @@ +variable "length" { + default = 1 + type = number +} \ No newline at end of file diff --git a/tests/iac-id-tokens/tests/main.tftest.hcl b/tests/iac-id-tokens/tests/main.tftest.hcl new file mode 100644 index 0000000000000000000000000000000000000000..fedf96e4c458eee084740b05980a52ffe64362a1 --- /dev/null +++ b/tests/iac-id-tokens/tests/main.tftest.hcl @@ -0,0 +1,6 @@ +run "test" { + assert { + condition = file(local_file.foo.filename) == "foo!" + error_message = "Incorrect content in ${local_file.foo.filename}" + } +} diff --git a/tests/iac-id-tokens/varfile.integration-test.tfvars b/tests/iac-id-tokens/varfile.integration-test.tfvars new file mode 100644 index 0000000000000000000000000000000000000000..a9e6ed522698bc6187641fb135c39346cd4223e2 --- /dev/null +++ b/tests/iac-id-tokens/varfile.integration-test.tfvars @@ -0,0 +1 @@ +test_variable = "varfile integration test" diff --git a/tests/integration-tests/IdTokens.gitlab-ci.yml b/tests/integration-tests/IdTokens.gitlab-ci.yml new file mode 100644 index 0000000000000000000000000000000000000000..7d4078d45a74932fc66319c63e0385a0872d8514 --- /dev/null +++ b/tests/integration-tests/IdTokens.gitlab-ci.yml @@ -0,0 +1,112 @@ +include: + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/validate@$CI_COMMIT_SHA + inputs: + image_registry_base: $GITLAB_OPENTOFU_IMAGE_BASE + version: $CI_COMMIT_SHA + base_os: $GITLAB_OPENTOFU_BASE_IMAGE_OS + opentofu_version: $OPENTOFU_VERSION + root_dir: $TEST_GITLAB_TOFU_ROOT_DIR + stage: validate + state_name: $TEST_GITLAB_TOFU_STATE_NAME + rules: [{when: always}] + enable_id_tokens: true + id_tokens_setup_script: $TEST_GITLAB_TOFU_ROOT_DIR/id-tokens-setup.sh + + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/test@$CI_COMMIT_SHA + inputs: + image_registry_base: $GITLAB_OPENTOFU_IMAGE_BASE + version: $CI_COMMIT_SHA + base_os: $GITLAB_OPENTOFU_BASE_IMAGE_OS + opentofu_version: $OPENTOFU_VERSION + root_dir: $TEST_GITLAB_TOFU_ROOT_DIR + stage: test + state_name: $TEST_GITLAB_TOFU_STATE_NAME + rules: [{when: always}] + enable_id_tokens: true + id_tokens_setup_script: $TEST_GITLAB_TOFU_ROOT_DIR/id-tokens-setup.sh + + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/graph@$CI_COMMIT_SHA + inputs: + image_registry_base: $GITLAB_OPENTOFU_IMAGE_BASE + version: $CI_COMMIT_SHA + base_os: $GITLAB_OPENTOFU_BASE_IMAGE_OS + opentofu_version: $OPENTOFU_VERSION + root_dir: $TEST_GITLAB_TOFU_ROOT_DIR + stage: graph + state_name: $TEST_GITLAB_TOFU_STATE_NAME + rules: [{when: always}] + enable_id_tokens: true + id_tokens_setup_script: $TEST_GITLAB_TOFU_ROOT_DIR/id-tokens-setup.sh + + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/plan@$CI_COMMIT_SHA + inputs: + image_registry_base: $GITLAB_OPENTOFU_IMAGE_BASE + version: $CI_COMMIT_SHA + base_os: $GITLAB_OPENTOFU_BASE_IMAGE_OS + opentofu_version: $OPENTOFU_VERSION + root_dir: $TEST_GITLAB_TOFU_ROOT_DIR + stage: plan + state_name: $TEST_GITLAB_TOFU_STATE_NAME + rules: [{when: always}] + enable_id_tokens: true + id_tokens_setup_script: $TEST_GITLAB_TOFU_ROOT_DIR/id-tokens-setup.sh + + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/apply@$CI_COMMIT_SHA + inputs: + image_registry_base: $GITLAB_OPENTOFU_IMAGE_BASE + version: $CI_COMMIT_SHA + base_os: $GITLAB_OPENTOFU_BASE_IMAGE_OS + opentofu_version: $OPENTOFU_VERSION + root_dir: $TEST_GITLAB_TOFU_ROOT_DIR + stage: apply + state_name: $TEST_GITLAB_TOFU_STATE_NAME + rules: [{when: always}] + enable_id_tokens: true + id_tokens_setup_script: $TEST_GITLAB_TOFU_ROOT_DIR/id-tokens-setup.sh + + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/destroy@$CI_COMMIT_SHA + inputs: + image_registry_base: $GITLAB_OPENTOFU_IMAGE_BASE + version: $CI_COMMIT_SHA + base_os: $GITLAB_OPENTOFU_BASE_IMAGE_OS + opentofu_version: $OPENTOFU_VERSION + root_dir: $TEST_GITLAB_TOFU_ROOT_DIR + stage: destroy + state_name: $TEST_GITLAB_TOFU_STATE_NAME + rules: [{when: always}] + enable_id_tokens: true + id_tokens_setup_script: $TEST_GITLAB_TOFU_ROOT_DIR/id-tokens-setup.sh + + # For CI Terraform state cleanup + - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/delete-state@$CI_COMMIT_SHA + inputs: + state_name: $TEST_GITLAB_TOFU_STATE_NAME + rules: [{when: always}] + +stages: [validate, test, graph, plan, apply, destroy, cleanup] + +.gitlab-tofu:id_tokens: + id_tokens: + GITLAB_OIDC_TOKEN: + aud: https://gitlab.com + +.check-id-tokens-setup-ran: &check_id_tokens_setup_ran + - test -f id-tokens-setup-ran + +validate: + after_script: *check_id_tokens_setup_ran + +test: + after_script: *check_id_tokens_setup_ran + +graph: + after_script: *check_id_tokens_setup_ran + +plan: + after_script: *check_id_tokens_setup_ran + +apply: + after_script: *check_id_tokens_setup_ran + +destroy: + after_script: *check_id_tokens_setup_ran diff --git a/tests/integration.gitlab-ci.yml b/tests/integration.gitlab-ci.yml index f5ed0b8e88b23543c0a6c8f2a335c8457b73ae6d..6f3be6dec59e66aba46d447e5132ea6a7c0dd80f 100644 --- a/tests/integration.gitlab-ci.yml +++ b/tests/integration.gitlab-ci.yml @@ -175,3 +175,21 @@ destroy-job-template: GITLAB_OPENTOFU_BASE_IMAGE_OS: - alpine - debian + +id-tokens: + stage: test-integration + variables: + OPENTOFU_VERSION: $LATEST_OPENTOFU_VERSION + TEST_GITLAB_TOFU_STATE_NAME: ci-integration-$CI_JOB_NAME_SLUG-$CI_PIPELINE_IID-$CI_NODE_INDEX + TEST_GITLAB_TOFU_ROOT_DIR: tests/iac-id-tokens + trigger: + include: tests/integration-tests/$PIPELINE_NAME.gitlab-ci.yml + strategy: depend + parallel: + matrix: + - PIPELINE_NAME: + - IdTokens + GITLAB_OPENTOFU_BASE_IMAGE_OS: + - alpine + - debian +