更新日:2026年8月7日
11分で読めます
スタック全体の認証情報管理をシンプルに。GitLab Secrets Managerは External Secrets Operator(ESO)、Terraform、Secrets Manager APIに対応し、CI/CD以外の ワークフローからもシークレットを安全に取得できます。

CI/CDにはCI/CD用、KubernetesにはKubernetes用、Terraformにはまた別のシークレットストア。こうした分散した状態は、決して珍しくありません。ただ、増え続ける管理対象のツール、そしてアクセス制御の整合性を取り続ける負担。何か問題が起きたときには、ばらばらの監査証跡を突き合わせるところから始めることになります。
GitLab Secrets Managerが、External Secrets Operator(ESO)とTerraformに対応しました。CI/CDパイプラインの外側でも、安全にシークレットを取得できるようになります。OpenBaoを基盤とするGitLab Secrets Managerは、ソフトウェアデリバリーチェーン全体でシークレットの信頼できる唯一の情報源となる存在。1つのシークレットストアを、次のすべての用途で共有できます。
ESOは、Vaultプロバイダーを介してGitLab Secrets Managerからシークレットを同期します。流れはシンプルです。クラスター内のワークロードが有効期間の短いJSON Web Token(JWT)を保持し、ESOがそれを使ってOpenBaoに認証。取得したシークレットは、Kubernetes Secretへ書き込まれます。

SecretStoreは、「どこからシークレットを取得し、どう認証するか」をESOに伝えるためのリソースです。GitLab Secrets ManagerはVault互換のKV v2 APIを公開しているため、設定にはVaultプロバイダーを指定します。namespaceフィールドが対応するのはGitLabの階層(Organization、グループ、プロジェクト)で、このストアから参照できるシークレットの範囲を決めるもの。認証に使うのは、GitLabが発行しKubernetes Secretに格納したJWTです。secretRefから参照します。
apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
name: gitlab-secrets-manager
namespace: my-app
spec:
provider:
vault:
server: https://secrets.gitlab.com # provider.vault.server
path: secrets/kv # provider.vault.path
version: v2
namespace: org_5/group_42/project_99 # provider.vault.namespace
auth:
jwt:
path: api_jwt/cel # provider.vault.auth.jwt.path
role: all_api # provider.vault.auth.jwt.role
secretRef:
name: gitlab-access-token # Kubernetes secret holding the minted token
key: token
ExternalSecretで定義するのは、「どのシークレットを取得し、どこに配置するか」です。先ほど作成したSecretStoreを参照し、リモートのシークレットをKubernetes Secretへマッピングします。あとはワークロードから、マウントまたは環境変数として参照するだけ。
ターゲットとなるシークレット(synced-secret)を作成し、管理するのはESOです。refreshIntervalで指定した間隔ごとにGitLabから再取得するため、値をローテーションしても再デプロイは不要。data配下の各エントリは、リモートのシークレット1つをターゲット側のキー1つに対応付けます。remoteRef.keyがGitLab Secrets Manager上のパス、propertyがそのシークレット内のフィールド、secretKeyがKubernetes側での格納先キーです。
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: my-secret
namespace: my-app
spec:
refreshInterval: 45m
secretStoreRef:
name: gitlab-secrets-manager
kind: SecretStore
target:
name: synced-secret
data:
- secretKey: value
remoteRef:
key: explicit/<secret_name> # <secrets_path>/<secret_name>
property: value
GitLab Secrets ManagerとESOを実際に組み合わせる手順は、チュートリアルで紹介しています。
Terraformのstateや.tfvarsファイルは、認証情報の流出経路になりやすい場所です。シークレットがそのままディスクに書き出されたり、気づかないうちにバージョン管理へコミットされたりするためです。回避策となるのが、GitLabのシークレットをデータソースとして読み込む方法。planやapplyの実行時に発行したJWTで認証します。Terraformから直接参照する形にすれば、.tfvarsファイルにもCI/CD変数にも認証情報を残さずに済みます。
data "external" "gitlab_secrets_token" {
program = ["bash", "${path.module}/scripts/mint_token.sh"]
query = {
project_id = var.gitlab_project_id
}
}
provider "vault" {
address = data.external.gitlab_secrets_token.result.server
namespace = data.external.gitlab_secrets_token.result.namespace
auth_login_jwt {
mount = data.external.gitlab_secrets_token.result.auth_path
role = data.external.gitlab_secrets_token.result.role
jwt = data.external.gitlab_secrets_token.result.jwt
}
}
data "vault_kv_secret_v2" "my_secret" {
mount = data.external.gitlab_secrets_token.result.mount
name = "${data.external.gitlab_secrets_token.result.secrets_path}/<secret_name>"
}
output "secret_value" {
value = data.vault_kv_secret_v2.my_secret.data["value"]
sensitive = true
}
Terraformでシークレットを読み取る方法は、ドキュメントで詳しく解説しています。
すべてのワークフローがAPIを直接呼び出すわけではありません。Vault互換のツールを前提にスクリプトを組んでいるチームなら、OpenBaoまたはVault CLIがそのまま使えます。手順はVaultから読み取るときと同じ。GitLab Secrets Managerのシークレットをそのまま取得できます。
export VAULT_ADDR="<server>"
export VAULT_NAMESPACE="<namespace>"
# Exchange the minted JWT for an OpenBao token, then export it.
vault write "auth/<auth_jwt_path>/login" role=<role> jwt=<token>
export VAULT_TOKEN="<client_token>"
# Read the secret value.
vault kv get -mount=<path> "<secrets_path>/<secret_name>"
GitLab CI/CD、Kubernetes、Terraformのどれにも当てはまらない自動化には、Secrets Manager APIという選択肢があります。認証情報をハードコーディングしたり、変数ファイルを別途用意したりしなくても、任意の外部システムからSecrets Managerのシークレットを取得できます。
# Request JWT token using Service Account
RESPONSE=$(curl --silent --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/projects/<project_id>/secrets_manager/access_token")
SERVER=$(echo "$RESPONSE" | jq --raw-output .provider.vault.server)
NAMESPACE=$(echo "$RESPONSE" | jq --raw-output .provider.vault.namespace)
MOUNT=$(echo "$RESPONSE" | jq --raw-output .provider.vault.path)
SECRETS_PATH=$(echo "$RESPONSE" | jq --raw-output .provider.vault.secrets_path)
AUTH_PATH=$(echo "$RESPONSE" | jq --raw-output .provider.vault.auth.jwt.path)
ROLE=$(echo "$RESPONSE" | jq --raw-output .provider.vault.auth.jwt.role)
JWT=$(echo "$RESPONSE" | jq --raw-output .provider.vault.auth.jwt.token)
# Exchange the JWT for a short-lived OpenBao token.
VAULT_TOKEN=$(curl --silent --request POST \
--header "X-Vault-Namespace: $NAMESPACE" \
--data "{\"role\":\"$ROLE\",\"jwt\":\"$JWT\"}" \
"$SERVER/v1/auth/$AUTH_PATH/login" | jq --raw-output .auth.client_token)
# Read the secret value.
curl --silent \
--header "X-Vault-Token: $VAULT_TOKEN" \
--header "X-Vault-Namespace: $NAMESPACE" \
"$SERVER/v1/$MOUNT/data/$SECRETS_PATH/<secret_name>"
GitLab Secrets Managerは、PremiumおよびUltimateのお客様向けにパブリックベータとして提供中です。ESO、Terraform、APIによるシークレットへのアクセスに対応しているのは、現時点でGitLab.comとGitLab Self-Managed。GitLab Dedicatedへの対応も近日中を予定しています。
ベータ期間中は無料でご利用いただけます。一般提供の開始後は、GitLabクレジットによる課金対象の有料機能となる予定。課金が始まる前にはオプトインが必要で、事前にご案内します。
まずはドキュメントをご覧ください。足りない点やご要望があれば、こちらのイシューへお寄せください。一般提供に向けて、フィードバックを集めています。
このブログ記事を楽しんでいただけましたか?ご質問やフィードバックがあればお知らせください。GitLabコミュニティフォーラムで新しいトピックを作成してあなたの声を届けましょう。
フィードバックを共有する