OIDC を使って CircleCI から簡単に HashiCorp Vault と認証+シークレットアクセスできる Orb を書いてみた
書いてみたのはこれ:
これを使えば、CircleCI の環境変数に静的に保存していたシークレットから卒業できそうですね。
CircleCI の OIDC サポート
つい最近サポートされたみたいです。
GitHub Actions や GitLab では以前から既にサポートされていて、GitHub Actions での例は以前にも記事に書きました:
今回は CircleCI で、Orb を使って同様の workflow を実現してみます。
Organization ID を確認
Vault 側で OIDC の設定を構成するためには、利用している CircleCI アカウントの Organization ID が必要になります。Organization ID を確認するには、CircleCI のコンソールから Organization Settings
ページに行くことで確認できます。
※最低1つの Context が作成されていないと Organization ID が表示されません。
Vault の設定
基本的には前回書いた GitHub Actions OIDC の時とほとんど同じです。
JWT Auth Method を有効にする
$ vault auth enable jwt
Success! Enabled jwt auth method at: jwt/
有効にした JWT auth method config の bound_issuer
と oidc_discovery_url
フィールドを設定します。ここで先ほど確認した Organization ID が必要になります。${CIRCLECI_ORG_ID}
を自分のものと置き換えてください。
$ vault write auth/jwt/config \
bound_issuer="https://oidc.circleci.com/org/${CIRCLECI_ORG_ID}" \
oidc_discovery_url="https://oidc.circleci.com/org/${CIRCLECI_ORG_ID}"
Success! Data written to: auth/jwt/config
JWT auth backend role の作成
$ vault write auth/jwt/role/circleci-dev -<<EOF
{
"role_type": "jwt",
"user_claim": "sub",
"bound_claims": {
"aud": "${CIRCLECI_ORG_ID}"
},
"policies": ["circleci-dev"],
"ttl": "1h"
}
EOF
利用できる claim の種類は GitHub などと比べると少し少ないようですが、一覧は下記から確認できます:
今回の例では aud
のみを bound_claims
条件に含めているので、自分の Orgnization ID からの要求であれば全て受け付けます。もう少し条件を絞りたい場合は、例えば代わりに oidc.circleci.com/project-id
を使って、特定の Project ID からの要求のみ信頼する、といった制御もできるかと思います。
今回は詳細は割愛しますが、上記の例では、policies
で指定されているように、circleci-dev
という ACL Policy が別に存在し、目的の secret path への必要な permission が正しく grant されている前提です。
$ vault kv put secret/circleci/dev password=foo
$ vault policy write circleci-dev -<<EOF
path "secret/data/circleci/dev" {
capabilities = ["read"]
}
EOF
実際に Orb を使ってみる
では実際に workflow から Vault へ OIDC 経由で認証し、任意のシークレットを取得してみます。
description: |
Install Vault binary, authenticate using OIDC, and get secrets.
usage:
version: 2.1
orbs:
orb-hashicorp-vault-cli: smaeda-ks/orb-hashicorp-vault-cli@0.1.3
jobs:
my-job:
machine: true
steps:
- checkout
# Install Vault
- orb-hashicorp-vault-cli/install
# Authenticate using OIDC and obtain token
# This will automatically set VAULT_TOKEN env variable
- orb-hashicorp-vault-cli/auth-oidc:
vault-address: "http://localhost:8200"
vault-role: "circleci-dev"
- run:
name: Get secret
command: |
# export secret using $BASH_ENV
# so it can be referenced by subsequent steps within the job
FOO=$(vault kv get -field=password secret/circleci/dev)
echo "export SECRET_FOO=${FOO}" >> $BASH_ENV
workflows:
use-my-orb:
jobs:
- my-job
今回作った Orb は、install
と auth-oidc
の2つのコマンドのみ提供しています。
install
コマンドを使うと、現在利用している executor 上に Vault の実行ファイルをダウンロードし、パスを通してくれます。これによって以降の step では vault
コマンドが利用可能になります。
auth-oidc
コマンドを使うと、CircleCI から払い出された JWT トークンを使って、リモートの Vault と認証し、token を取得します。この時取得した token は自動的に VAULT_TOKEN
環境変数にセットされるため、auth-oidc
を実行後は Vault にログイン済みの状態で vault
コマンドを利用可能になっています。
なお、vault-address
と vault-role
は required なパラメーターなので、必ず指定が必要です。vault-role
には、事前に作成した JWT auth backend の role を指定します。今回のケースでは circleci-dev
ですね。有償版 Vault を利用している場合には、Namespace などもオプションで指定できるので、詳細はドキュメントをご覧ください:
これら2つのコマンドを実行したのち、上記の例では最後の step で、secret/circleci/dev
path に保存されている password
のデータを取得しています。実際の workflow では、これを更に後続の step から利用することになるでしょう。
その他
今回作った Orb は私の個人の Namespace に紐付いており、CircleCI から verify されている訳ではないので、CircleCI の org 設定で未承認 Orb の利用を許可しておく必要があります。
Discussion