diff --git a/.woodpecker/flux-reconcile-source.yaml b/.woodpecker/flux-reconcile-source.yaml new file mode 100644 index 0000000..fa6fb58 --- /dev/null +++ b/.woodpecker/flux-reconcile-source.yaml @@ -0,0 +1,50 @@ +when: + - event: push + branch: fresh-start + +skip_clone: true + +steps: + - name: Get kubernetes access from OpenBao + image: quay.io/openbao/openbao:2.5.2 + environment: + VAULT_ADDR: https://openbao.lumpiasty.xyz:8200 + ROLE_ID: + from_secret: flux_reconcile_role_id + SECRET_ID: + from_secret: flux_reconcile_secret_id + commands: + - bao write -field token auth/approle/login + role_id=$ROLE_ID + secret_id=$SECRET_ID > /woodpecker/.vault_id + - export VAULT_TOKEN=$(cat /woodpecker/.vault_id) + - bao write -format json -f /kubernetes/creds/flux-reconcile > /woodpecker/kube_credentials + - bao read -format + - name: Construct Kubeconfig + image: alpine/k8s:1.32.13 + environment: + KUBECONFIG: /woodpecker/kubeconfig + commands: + - kubectl config set-cluster cluster + --server=https://$KUBERNETES_SERVICE_HOST + --client-certificate=/run/secrets/kubernetes.io/serviceaccount/ca.crt + - kubectl config set-credentials cluster + --token=$(jq -r .data.service_account_token /woodpecker/kube_credentials) + - kubectl config set-context cluster + --cluster cluster + --user cluster + --namespace flux-system + --current=true + - name: Reconcile git source + image: ghcr.io/fluxcd/flux-cli:v2.8.3 + environment: + KUBECONFIG: /woodpecker/kubeconfig + commands: + - flux reconcile source git flux-system + - name: Invalidate OpenBao token + image: quay.io/openbao/openbao:2.5.2 + environment: + VAULT_ADDR: https://openbao.lumpiasty.xyz:8200 + commands: + - export VAULT_TOKEN=$(cat /woodpecker/.vault_id) + - bao write -f auth/token/revoke-self diff --git a/utils/synchronize-vault.py b/utils/synchronize-vault.py index f8562a0..9f3609a 100755 --- a/utils/synchronize-vault.py +++ b/utils/synchronize-vault.py @@ -73,6 +73,28 @@ def synchronize_approle_auth(client: hvac.Client): print('Enabling AppRole auth method') client.sys.enable_auth_method('approle', 'AppRole authorization for CI') + roles_dir = pathlib.Path(__file__).parent.joinpath('../vault/approles/') + roles: dict[str, Any] = {} + + for filename in roles_dir.iterdir(): + with filename.open('r') as f: + role = yaml.safe_load(f.read()) + assert type(role) is dict + roles[filename.stem] = role + + roles_on_vault: list[str] = [] + roles_response = client.list("auth/approle/roles") + if roles_response is not None: + roles_on_vault = roles_response['data']['keys'] + + for role in roles_on_vault: + if role not in roles: + print(f'Deleting role: {role}') + client.delete(f'auth/approle/role/{role}') + + for role_name, role_content in roles.items(): + print(f'Updating role: {role_name}') + client.write_data(f'auth/approle/role/{role_name}', data=role_content) def synchronize_kubernetes_secretengine(client: hvac.Client): # Ensure kubernetes secret engine is enabled diff --git a/vault/approles/ci-flux-reconcile.yaml b/vault/approles/ci-flux-reconcile.yaml new file mode 100644 index 0000000..6b56f23 --- /dev/null +++ b/vault/approles/ci-flux-reconcile.yaml @@ -0,0 +1,4 @@ +token_ttl: 20m +token_max_ttl: 20m +policies: + - flux-reconcile \ No newline at end of file diff --git a/vault/policy/flux-reconcile.hcl b/vault/policy/flux-reconcile.hcl new file mode 100644 index 0000000..e54af12 --- /dev/null +++ b/vault/policy/flux-reconcile.hcl @@ -0,0 +1,3 @@ +path "kubernetes/creds/flux-reconcile" { + capabilities = ["update"] +}