From fa0df6f175452996c74e39f173517b7a8dfc2c79 Mon Sep 17 00:00:00 2001 From: Gabriel Radureau Date: Tue, 5 Nov 2024 16:33:58 +0100 Subject: [PATCH] create gitea tofu bot user --- .gitea/workflows/iac.yaml | 61 +++++++++++++++++++ .../playbooks/tools/hashicorp_vault.yml | 11 ++++ .../hashicorp_vault/files/hashicorp_vault.tf | 15 +++++ .../hashicorp_vault/tasks/gitea_oidc_auth.yml | 1 + iac/backend.tf | 2 +- iac/main.tf | 31 ++++++++++ iac/providers.tf | 25 ++++++++ 7 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 .gitea/workflows/iac.yaml create mode 100644 iac/main.tf create mode 100644 iac/providers.tf diff --git a/.gitea/workflows/iac.yaml b/.gitea/workflows/iac.yaml new file mode 100644 index 0000000..026a3e4 --- /dev/null +++ b/.gitea/workflows/iac.yaml @@ -0,0 +1,61 @@ +--- +# template source: https://github.com/bretfisher/docker-build-workflow/blob/main/templates/call-docker-build.yaml +name: Postgres + +on: #[push,pull_request] + push: &tofuPaths + paths: + - 'iac/*.tf' + - 'iac/*.tfvars' + - 'iac/**/*.tf' + - 'iac/**/*.tfvars' + pull_request: *tofuPaths + +# cancel any previously-started, yet still active runs of this workflow on the same branch +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +.vault_step: &vault_step + name: read vault secret + uses: https://gitea.arcodange.duckdns.org/arcodange-org/vault-action.git@main + id: vault-secrets + with: + url: https://vault.arcodange.duckdns.org + jwtGiteaOIDC: ${{ needs.gitea_vault_auth.outputs.gitea_vault_jwt }} + role: gitea_cicd + method: jwt + path: gitea_jwt + secrets: | + kvv1/google/credentials credentials | GOOGLE_BACKEND_CREDENTIALS ; + kvv1/admin/gitea token | GITEA_TOKEN + +jobs: + gitea_vault_auth: + name: Auth with gitea for vault + runs-on: ubuntu-latest + outputs: + gitea_vault_jwt: ${{steps.gitea_vault_jwt.outputs.id_token}} + steps: + + - name: Auth with gitea for vault + id: gitea_vault_jwt + run: | + echo -n "${{ secrets.vault_oauth__sh_b64 }}" | base64 -d | bash + + tofu: + name: Tofu + needs: + - gitea_vault_auth + runs-on: ubuntu-latest + env: + OPENTOFU_VERSION: 1.8.2 + TERRAFORM_VAULT_AUTH_JWT: ${{ needs.gitea_vault_auth.outputs.gitea_vault_jwt }} + steps: + - *vault_step + - uses: actions/checkout@v4 + - name: terraform apply + uses: dflook/terraform-apply@v1 + with: + path: iac + auto_approve: true \ No newline at end of file diff --git a/ansible/arcodange/factory/playbooks/tools/hashicorp_vault.yml b/ansible/arcodange/factory/playbooks/tools/hashicorp_vault.yml index 6f6ef52..742c912 100644 --- a/ansible/arcodange/factory/playbooks/tools/hashicorp_vault.yml +++ b/ansible/arcodange/factory/playbooks/tools/hashicorp_vault.yml @@ -14,6 +14,16 @@ tasks: + - name: Generate GITEA_ADMIN_TOKEN + run_once: True + include_role: + name: arcodange.factory.gitea_token + vars: + gitea_token_name: GITEA_ADMIN_TOKEN + gitea_token_fact_name: vault_GITEA_ADMIN_TOKEN + gitea_token_scopes: write:admin,write:organization,write:repository,write:user + gitea_token_replace: true + - name: Setup Hashicorp Vault include_role: name: hashicorp_vault @@ -23,6 +33,7 @@ postgres_admin_credentials: username: '{{ pg_conf.POSTGRES_USER }}' password: '{{ pg_conf.POSTGRES_PASSWORD }}' + gitea_admin_token: '{{ vault_GITEA_ADMIN_TOKEN }}' - name: share VAULT CA block: diff --git a/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/files/hashicorp_vault.tf b/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/files/hashicorp_vault.tf index 7c289a6..e2b35a1 100644 --- a/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/files/hashicorp_vault.tf +++ b/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/files/hashicorp_vault.tf @@ -34,6 +34,11 @@ variable "postgres_admin_credentials" { sensitive = true } +variable "gitea_admin_token" { + type = string + sensitive = true +} + # kubectl -n kube-system exec $(kubectl -n kube-system get pod -l app.kubernetes.io/name=traefik -o jsonpath="{.items[0]['.metadata.name']}") -- cat /data/acme.json | jq '(.letsencrypt.Certificates | map(select(.domain.main=="arcodange.duckdns.org")))[0]' | jq '.certificate' -r | base64 -d | openssl x509 # variable "ca_pem" { # type = string @@ -178,6 +183,16 @@ resource "vault_kv_secret" "gitea_app_id" { resource "vault_kv_secret" "postgres_admin_credentials" { path = "${vault_mount.kvv1.path}/postgres/credentials" data_json = jsonencode(var.postgres_admin_credentials) + lifecycle { + ignore_changes = [ data_json ] # in case vault changed credentials - do over if pg user is reset outside of vault + } +} + +resource "vault_kv_secret" "gitea_admin_token" { + path = "${vault_mount.kvv1.path}/admin/gitea" + data_json = jsonencode({ + token = var.gitea_admin_token + }) } resource "vault_audit" "stdout" { diff --git a/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/tasks/gitea_oidc_auth.yml b/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/tasks/gitea_oidc_auth.yml index e7edccb..3a04fb9 100644 --- a/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/tasks/gitea_oidc_auth.yml +++ b/ansible/arcodange/factory/playbooks/tools/roles/hashicorp_vault/tasks/gitea_oidc_auth.yml @@ -43,6 +43,7 @@ -var='vault_address={{ vault_address }}' -var='vault_token={{ vault_root_token }}' -var='postgres_admin_credentials={{ postgres_admin_credentials | to_json }}' + -var='gitea_admin_token={{ gitea_admin_token }}' loop_control: loop_var: command extended: true diff --git a/iac/backend.tf b/iac/backend.tf index 29f73f7..df0804c 100644 --- a/iac/backend.tf +++ b/iac/backend.tf @@ -1,6 +1,6 @@ terraform { backend "gcs" { bucket = "arcodange-tf" - prefix = "tofu/code" + prefix = "factory/main" } } \ No newline at end of file diff --git a/iac/main.tf b/iac/main.tf new file mode 100644 index 0000000..ad5f1f1 --- /dev/null +++ b/iac/main.tf @@ -0,0 +1,31 @@ + +resource "random_password" "tofu" { + length = 32 +} +resource "gitea_user" "tofu" { + username = "tofu_module_reader" + login_name = "tofu_module_reader" + password = random_password.tofu.result + email = "tofu-module-reader@arcodange.fake" + must_change_password = false + full_name = "restricted CI user" + prohibit_login = true + restricted = true + visibility = "private" +} +resource "tls_private_key" "tofu" { + algorithm = "ED25519" +} +resource "gitea_public_key" "tofu" { + title = "tofu" + key = tls_private_key.tofu.public_key_openssh + username = gitea_user.tofu.username +} + +resource "vault_kv_secret" "gitea_admin_token" { + path = "kvv1/gitea/tofu_module_reader" + data_json = jsonencode({ + ssh_private_key = tls_private_key.tofu.private_key_openssh + ssh_public_key = tls_private_key.tofu.public_key_openssh + }) +} \ No newline at end of file diff --git a/iac/providers.tf b/iac/providers.tf new file mode 100644 index 0000000..566ce48 --- /dev/null +++ b/iac/providers.tf @@ -0,0 +1,25 @@ +terraform { + required_providers { + gitea = { + source = "go-gitea/gitea" + version = "0.5.1" + } + vault = { + source = "vault" + version = "4.4.0" + } + } +} + +provider "gitea" { # https://registry.terraform.io/providers/go-gitea/gitea/latest/docs + base_url = "https://gitea.arcodange.duckdns.org" + # use GITEA_TOKEN env var +} + +provider vault { + address = "https://vault.arcodange.duckdns.org" + auth_login_jwt { # TERRAFORM_VAULT_AUTH_JWT environment variable + mount = "gitea_jwt" + role = "gitea_cicd" + } +} \ No newline at end of file