正式なドキュメントは英語版であり、この日本語訳はAI支援翻訳により作成された参考用のものです。日本語訳の一部の内容は人間によるレビューがまだ行われていないため、翻訳のタイミングにより英語版との間に差異が生じることがあります。最新かつ正確な情報については、英語版をご参照ください。

GitLab CI/CDでHashiCorp Vaultシークレットを使用する

  • プラン: Premium、Ultimate
  • 提供形態: GitLab.com、GitLab Self-Managed、GitLab Dedicated

GitLab CI/CDでHashiCorp Vaultのシークレットを使用できます。IDトークンを使用して、HashiCorp Vaultで認証する

CIジョブでVaultのシークレットを使用する前に、Vaultサーバーを設定する必要があります。HashiCorp Vaultを使用した認証とシークレットの読み取りのチュートリアルには、IDトークンを使用した認証に関する詳細が記載されています。

以下の例では、vault.example.comのURLをVaultサーバーのURLに、gitlab.example.comをGitLabインスタンスのURLに置き換えてください。

Vaultサーバーを設定する

Vaultサーバーを設定するには:

  1. 次のコマンドを実行して認証方法を有効にします。これらは、GitLabインスタンスのOIDC Discovery URLをVaultサーバーに提供するため、Vaultは公開署名キーをフェッチし、認証時にJSON Webトークン(JWT)を検証できます:

    $ vault auth enable jwt
    
    $ vault write auth/jwt/config \
      oidc_discovery_url="https://gitlab.example.com" \
      bound_issuer="gitlab.example.com"
  2. 特定のパスおよびオペレーションへのアクセスを許可または禁止するようにVaultサーバーでポリシーを設定します。この例では、本番環境に必要なシークレットのセットへの読み取りアクセスを許可します:

    vault policy write myproject-production - <<EOF
    # Read-only permission on 'ops/data/production/*' path
    
    path "ops/data/production/*" {
      capabilities = [ "read" ]
    }
    EOF
  3. プロジェクトまたはネームスペースに制限して、Vaultサーバーのロールを設定します。

  4. Vaultサーバーの詳細を提供するには、次のCI/CD変数を作成します:

    • VAULT_SERVER_URL: :VaultサーバーのURL。例:https://vault.example.com:8200
    • VAULT_AUTH_ROLE: オプション。認証を試行するときに使用するロール。ロールが指定されていない場合、Vaultは、認証方法の設定時に指定されたデフォルトロールを使用します。
    • VAULT_AUTH_PATH: オプション。認証方法がマウントされているパス。デフォルトはjwtです。
    • VAULT_NAMESPACE: オプション。シークレットの読み取りと認証に使用するVault Enterpriseネームスペース。以下のとおりになります:
      • Vaultでは、ネームスペースが指定されていない場合はroot(「/」)ネームスペースが使用されます。
      • Vaultオープンソースでは、この設定は無視されます。
      • HashiCorp Cloud Platform(HCP)Vaultでは、ネームスペースが必要です。HCP Vaultは、デフォルトでadminネームスペースをルートネームスペースとして使用します。たとえばVAULT_NAMESPACE=adminなどです。

サーバーロールを構成する

CIジョブは、認証を試行するときにロールを指定します。ロールを使用して、さまざまなポリシーをグループ化できます。認証が成功すると、これらのポリシーが結果のVaultトークンにアタッチされます。

バインドされたクレームは、JWTクレームに一致する定義済みの値です。バインドされたクレームを使用すると、特定のGitLabユーザー、特定のプロジェクト、または特定のGit参照に対して実行されているジョブへのアクセスを制限できます。バインドされたクレームは、必要に応じていくつでも持つことができますが、認証を成功させるには、すべてが一致する必要があります。

バインドされたクレームをユーザーロール保護ブランチなどのGitLab機能と組み合わせることで、これらのルールを調整して、特定のユースケースに適合させることができます。この例では、認証が許可されるのは、本番環境リリースに使用されるパターンに一致する名前の保護されたタグに対して実行されているジョブのみです:

$ vault write auth/jwt/role/myproject-production - <<EOF
{
  "role_type": "jwt",
  "policies": ["myproject-production"],
  "token_explicit_max_ttl": 60,
  "user_claim": "user_email",
  "bound_audiences": "https://vault.example.com",
  "bound_claims_type": "glob",
  "bound_claims": {
    "project_id": "42",
    "ref_protected": "true",
    "ref_type": "tag",
    "ref": "auto-deploy-*"
  }
}
EOF

提供されたクレーム(project_idnamespace_idなど)のいずれかを使用して、常にロールをプロジェクトまたはネームスペースに制限してください。このように制限しないと、このGitLabインスタンスによって生成されたJWTは、このロールを使用して認証できる可能性があります。

IDトークンJWTクレームの完全なリストについては、GitLab CI/CDでHashiCorp Vaultのシークレットを使用するチュートリアルをレビューしてください。

有効期限、IPアドレス範囲、使用回数など、結果のVaultトークンにいくつかの属性を指定することもできます。オプションの完全なリストは、JSON Webトークンメソッドのロールの作成に関するVaultのドキュメントに記載されています。

CIジョブでVaultのシークレットを使用する

ジョブに少なくとも1つのIDトークンが定義されている場合、secretsキーワードは、そのトークンを自動的に使用してVaultで認証します。

Vaultサーバーの構成後、Vaultに保存されているシークレットを使用するには、secrets:vaultキーワードを使用します:

job_using_vault:
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com
  secrets:
    DATABASE_PASSWORD:
      vault: production/db/password@ops
      token: $VAULT_ID_TOKEN

この例では:

  • production/dbは、シークレットのパスです。
  • passwordは、フィールドです。
  • opsは、シークレットエンジンがマウントされているパスです。
  • production/db/password@opsは、ops/data/production/dbのパスに変換されます。
  • 認証は$VAULT_ID_TOKENを使用します。

GitLabがVaultからシークレットをフェッチした後、値は一時ファイルに保存されます。このファイルのパスは、fileタイプの変数と同様に、DATABASE_PASSWORDという名前のCI/CD変数に保存されます。

デフォルトの動作を上書きするには、fileオプションを明示的に設定します:

secrets:
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com
  DATABASE_PASSWORD:
    vault: production/db/password@ops
    file: false
    token: $VAULT_ID_TOKEN

この例では、シークレット値は、それを保持するファイルを指すのではなく、DATABASE_PASSWORD変数に直接配置されます。

シークレットエンジン

GitLab Runnerは、secrets:engine:nameキーワードで異なるシークレットエンジンをサポートしています:

シークレットエンジンsecrets:engine:nameの値Runnerバージョン詳細
KVシークレットエンジン - バージョン2kv-v213.4kv-v2は、エンジンタイプが明示的に指定されていない場合にGitLab Runnerが使用するデフォルトのエンジンです。
KVシークレットエンジン - バージョン1kv-v1またはgeneric13.4genericキーワードのサポートは、GitLab 15.11で導入されました。
<AWSシークレットエンジンgeneric16.11
HashiCorp Vault Artifactory Secrets Plugingeneric16.11このシークレットバックエンドは、JFrog Artifactoryサーバー(5.0.0以降)と通信し、指定されたスコープでアクセストークンを動的にプロビジョニングします。

別のシークレットエンジンを使用する

デフォルトでは、kv-v2シークレットエンジンが使用されます。別のエンジンを使用するには、設定のvaultの下にengineセクションを追加します。

たとえば、Artifactoryのシークレットエンジンとパスを設定するには、次のようにします:

job_using_vault:
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com
  secrets:
    JFROG_TOKEN:
      vault:
        engine:
          name: generic
          path: artifactory
        path: production/jfrog
        field: access_token
      file: false

この例では、シークレット値はartifactory/production/jfrogからフィールドaccess_tokenで取得されます。

トラブルシューティング

自己署名証明書エラー: certificate signed by unknown authority

Vaultサーバーが自己署名証明書を使用している場合、ジョブログに次のエラーが出力されます:

ERROR: Job failed (system failure): resolving secrets: initializing Vault service: preparing authenticated client: checking Vault server health: Get https://vault.example.com:8000/v1/sys/health?drsecondarycode=299&performancestandbycode=299&sealedcode=299&standbycode=299&uninitcode=299: x509: certificate signed by unknown authority

このエラーを解決するには、2つのオプションがあります:

  • 自己署名証明書をGitLab RunnerサーバーのCAストアに追加します。Helmチャートを使用してGitLab Runnerをデプロイした場合は、独自のGitLab Runnerイメージを作成する必要があります。
  • VAULT_CACERT環境変数を使用して、証明書を信頼するようにGitLab Runnerを設定します:
    • systemdを使用してGitLab Runnerを管理している場合は、GitLab Runnerの環境変数を追加する方法を参照してください。
    • Helmチャートを使用してGitLab Runnerをデプロイした場合は、次のようにします:
      1. GitLabにアクセスするためのカスタム証明書を提供し、GitLabの証明書の代わりに、Vaultサーバーの証明書を必ず追加してください。GitLabインスタンスも自己署名証明書を使用している場合は、同じSecretに両方を追加できるはずです。

      2. values.yamlファイルに次の行を追加します:

        ## Replace both the <SECRET_NAME> and the <VAULT_CERTIFICATE>
        ## with the actual values you used to create the secret
        
        certsSecretName: <SECRET_NAME>
        
        envVars:
          - name: VAULT_CACERT
            value: "/home/gitlab-runner/.gitlab-runner/certs/<VAULT_CERTIFICATE>"

GitLab Development Kit(GDK)を使用して、開発モードでVaultサーバーをローカルで実行している場合も、このエラーが発生する可能性があります。Vaultサーバーの自己署名証明書を信頼するように手動でシステムに指示できます。このサンプルチュートリアルでは、macOSで同じことを行う方法について説明しています。

resolving secrets: secret not found: MY_SECRETエラー

GitLabがVaultでシークレットを見つけられない場合、次のエラーが表示されることがあります:

ERROR: Job failed (system failure): resolving secrets: secret not found: MY_SECRET

vault値がCI/CDジョブで正しく設定されていることを確認します。

Vault CLIでkvコマンドを使用して、シークレットを取得できるかどうかを確認し、CI/CD設定のvault値の構文決定に役立てることができます。たとえば、シークレットを取得するには、次のようにします:

$ vault kv get -field=password -namespace=admin -mount=ops "production/db"
this-is-a-password