diff --git a/fast/assets/templates/workflow-gitlab.yaml b/fast/assets/templates/workflow-gitlab.yaml new file mode 100644 index 00000000..101f5bed --- /dev/null +++ b/fast/assets/templates/workflow-gitlab.yaml @@ -0,0 +1,167 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +default: + image: + name: registry.gitlab.com/gitlab-org/terraform-images/releases/1.1 + +variables: + FAST_OUTPUTS_BUCKET: ${outputs_bucket} + FAST_SERVICE_ACCOUNT: ${service_account} + FAST_WIF_PROVIDER: ${identity_provider} + SSH_AUTH_SOCK: /tmp/ssh_agent.sock + TF_PROVIDERS_FILE: ${tf_providers_file} + TF_VAR_FILES: ${tf_var_files == [] ? "''" : join("\n ", tf_var_files)} + TF_VERSION: 1.1.7 + TF_ROOT: $${CI_PROJECT_DIR} # The relative path to the root directory of the Terraform project + +stages: + - gcp-auth + - tf-setup + - tf-init + - tf-validate + - tf-plan + - tf-apply + +cache: + key: "$${TF_ROOT}" + paths: + - $${TF_ROOT}/.terraform/ + - $${TF_ROOT}/.tf-setup/ + +# Configure GCP Auth with Access Token +gcp-auth: + stage: gcp-auth + script: + - | + PAYLOAD="$(cat <> gcp-auth.env + + if [ -z "$GOOGLE_OAUTH_ACCESS_TOKEN" ]; then exit 1; fi +# WIP - will have to find a better way of doing this + artifacts: + reports: + dotenv: gcp-auth.env + +# Downloading from bucket into cache +tf-setup: + stage: tf-setup + script: + - | + mkdir -p .tf-setup + curl -X GET \ + -H "Authorization: Bearer $GOOGLE_OAUTH_ACCESS_TOKEN" \ + -o ".tf-setup/$${TF_PROVIDERS_FILE}" \ + "https://storage.googleapis.com/$${FAST_OUTPUTS_BUCKET}/providers/$${TF_PROVIDERS_FILE}" + for f in $TF_VAR_FILES; do + curl -X GET \ + -H "Authorization: Bearer $GOOGLE_OAUTH_ACCESS_TOKEN" \ + -o ".tf-setup/$f" \ + "https://storage.googleapis.com/$${FAST_OUTPUTS_BUCKET}/tfvars/$f" + done + dependencies: + - gcp-auth + +# Terraform Init +tf-init: + stage: tf-init + script: + - | + ssh-agent -a $SSH_AUTH_SOCK > /dev/null + echo "$CICD_MODULES_KEY" | tr -d '\r' | ssh-add - > /dev/null + mkdir -p ~/.ssh + ssh-keyscan -H 'gitlab.com' >> ~/.ssh/known_hosts + ssh-keyscan gitlab.com | sort -u - ~/.ssh/known_hosts -o ~/.ssh/known_hosts + cd "$${TF_ROOT}" + cp -R .tf-setup/. . + gitlab-terraform init + dependencies: + - gcp-auth + +# Terraform Validate +tf-validate: + stage: tf-validate + script: + - | + ssh-agent -a $SSH_AUTH_SOCK > /dev/null + echo "$CICD_MODULES_KEY" | tr -d '\r' | ssh-add - > /dev/null + mkdir -p ~/.ssh + ssh-keyscan -H 'gitlab.com' >> ~/.ssh/known_hosts + ssh-keyscan gitlab.com | sort -u - ~/.ssh/known_hosts -o ~/.ssh/known_hosts + cd "$${TF_ROOT}" + cp -R .tf-setup/. . + gitlab-terraform validate + dependencies: + - gcp-auth + +# Terraform Plan +tf-plan: + stage: tf-plan + script: + - | + ssh-agent -a $SSH_AUTH_SOCK > /dev/null + echo "$CICD_MODULES_KEY" | tr -d '\r' | ssh-add - > /dev/null + mkdir -p ~/.ssh + ssh-keyscan -H 'gitlab.com' >> ~/.ssh/known_hosts + ssh-keyscan gitlab.com | sort -u - ~/.ssh/known_hosts -o ~/.ssh/known_hosts + cd "$${TF_ROOT}" + cp -R .tf-setup/. . + gitlab-terraform plan + gitlab-terraform plan-json + dependencies: + - gcp-auth + artifacts: + paths: + - $${TF_ROOT}/plan.cache + reports: + terraform: $${TF_ROOT}/plan.json + +# Terraform Apply +tf-apply: + stage: tf-apply + script: + - cd "$${TF_ROOT}" + - gitlab-terraform apply + when: manual + only: + variables: + - $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH + dependencies: + - gcp-auth \ No newline at end of file diff --git a/fast/stages/00-bootstrap/identity-providers.tf b/fast/stages/00-bootstrap/identity-providers.tf index 925b8eed..f202bb09 100644 --- a/fast/stages/00-bootstrap/identity-providers.tf +++ b/fast/stages/00-bootstrap/identity-providers.tf @@ -40,12 +40,12 @@ locals { "google.subject" = "assertion.sub" "attribute.sub" = "assertion.sub" "attribute.actor" = "assertion.actor" - "attribute.repository" = "assertion.repository" + "attribute.repository" = "assertion.project_path" "attribute.ref" = "assertion.ref" } allowed_audiences = ["https://gitlab.com"] issuer_uri = "https://gitlab.com" - principal_tpl = "principal://iam.googleapis.com/%s/subject/project_path:%s:ref_type:branch:ref:%s" + principal_tpl = "principalSet://iam.googleapis.com/%s/attribute.sub/project_path:%s:ref_type:branch:ref:%s" principalset_tpl = "principalSet://iam.googleapis.com/%s/attribute.repository/%s" } } diff --git a/fast/stages/00-bootstrap/outputs.tf b/fast/stages/00-bootstrap/outputs.tf index 45595c9e..d2b3eb8a 100644 --- a/fast/stages/00-bootstrap/outputs.tf +++ b/fast/stages/00-bootstrap/outputs.tf @@ -17,12 +17,12 @@ locals { _cicd_workflow_attrs = { bootstrap = { - service_account = module.automation-tf-bootstrap-sa.email + service_account = module.automation-tf-cicd-sa["bootstrap"].email tf_providers_file = "00-bootstrap-providers.tf" tf_var_files = [] } resman = { - service_account = module.automation-tf-resman-sa.email + service_account = module.automation-tf-cicd-sa["resman"].email tf_providers_file = "01-resman-providers.tf" tf_var_files = [ "00-bootstrap.auto.tfvars.json", diff --git a/fast/stages/00-bootstrap/variables.tf b/fast/stages/00-bootstrap/variables.tf index 1eb12c86..e046b367 100644 --- a/fast/stages/00-bootstrap/variables.tf +++ b/fast/stages/00-bootstrap/variables.tf @@ -61,7 +61,7 @@ variable "cicd_repositories" { condition = alltrue([ for k, v in coalesce(var.cicd_repositories, {}) : v == null || ( - contains(["github"], coalesce(try(v.type, null), "null")) + contains(["gitlab","github"], coalesce(try(v.type, null), "null")) ) ]) error_message = "Invalid repository type, supported types: 'github'."