Bitwardern CLI + sops で無料かつ安全に API Token を git 管理
備忘録
無料にこだわったやり方
※geminiを使って書いています。
やりたいこと
- 秘密鍵を生成
- Bitwardenに秘密鍵を格納
- API token暗号化しgit管理
- APIを叩く際にBitwardenから秘密鍵を取得、API tokenを複合して好きに使う(私の例ではcloudflare をterrafromを使って管理しています)
手順
0. 必要なツールのインストール
Macの場合、Homebrewを使って必要なCLIツールをインストールします。
brew install sops age bitwarden-cli
1. 秘密鍵の生成 (age)
age を使って、暗号化と復号に使うための鍵ペア(公開鍵・秘密鍵)を生成します。
age-keygen
# 実行すると、以下のように公開鍵と秘密鍵が出力されます
# Public key: age1lq...(長い公開鍵)...cqyma
# Private key: AGE-SECRET-KEY-1...(長い秘密鍵)...gqj7a
2. Bitwardenに秘密鍵を格納
- BitwardenのVault(Web版やデスクトップアプリ)で「セキュアノート」を新規作成します。
名前: SOPS Private Key (など、自分にとってわかりやすい名前)
ノート(メモ): 手順1で生成した 秘密鍵 (AGE-SECRET-KEY-1...で始まる行全体) を貼り付けて保存します。
-
Bitwarden CLIにログイン
bw login -
ターミナルで、今保存したアイテムの ID を取得します。
bw list items --search "SOPS Private Key"出力されるJSONの中から
"id": "..."の値(a1b2c3d4-....のようなUUID形式)をコピーして、控えておきます。
3. API token暗号化しgit管理 (sops)
-
sopsの設定ファイルを作成
プロジェクトのルートに.sops.yamlファイルを作成し、手順1で生成した 公開鍵 (age1...) を指定します。# .sops.yaml creation_rules: - age: 'age1lq...(ここにあなたの公開鍵)...cqyma' -
APIトークンファイルの暗号化
sopsコマンドで暗号化ファイルを作成します。Terraformで読み込むファイル名をsecrets.sops.yamlとします。sops secrets.sops.yaml -
コマンドを実行すると、ターミナル上でデフォルトのエディタ(
viやnanoなど)が起動します。そのエディタ上で、暗号化したいAPIトークンをYAML形式で入力します。(cloudflareは例です。)# エディタ内で入力する内容 api_token: "your-super-secret-api-token" -
ファイルを保存してエディタを終了します。
secrets.sops.yamlが作成され、中身が暗号化されていることが確認できます。 -
この
.sops.yaml(公開鍵の情報)とsecrets.sops.yaml(暗号化されたトークン)の2つをGitリポジトリにコミットします。秘密鍵は含まれていないため、安全にGit管理できます。
4. Terraformの設定
main.tf(または providers.tf)に sops プロバイダを追加し、暗号化ファイルを読み込む設定を記述します。
terraform {
required_providers {
# sopsプロバイダ
sops = {
source = "carlpett/sops"
version = "~> 1.0"
}
# Cloudflareプロバイダ (今回の例)
cloudflare = {
source = "cloudflare/cloudflare"
version = "~> 4.0"
}
}
}
# 1. sopsで暗号化ファイルをメモリ上に復号
data "sops_file" "secrets" {
source_file = "secrets.sops.yaml"
}
# 2. 復号した値をローカル変数に格納
locals {
# secrets.sops.yaml内の "cloudflare_api_token" キーを参照
cloudflare_api_token = data.sops_file.secrets.data["cloudflare_api_token"]
}
# 3. providerブロックでローカル変数を参照
provider "cloudflare" {
api_token = local.cloudflare_api_token
}
# 4. あとは好きにリソースを定義
resource "cloudflare_record" "example" {
# ...
}
terraform apply を実行する際に、Bitwardenから秘密鍵を取得して SOPS_AGE_KEY 環境変数に渡します。
-
Bitwarden Vaultのアンロック (セッション毎に1回):
bw unlockを実行し、セッションキーを環境変数BW_SESSIONにセットします。export BW_SESSION=$(bw unlock --raw) # Master Passwordの入力が求められます -
Terraformの実行:
SOPS_AGE_KEY環境変数に「Bitwardenから取得した秘密鍵」をセットしつつ、terraform applyを実行します。# <BitwardenのアイテムID> は手順2で取得したIDに置き換えてください SOPS_AGE_KEY=$(bw get notes <BitwardenのアイテムID> --session $BW_SESSION) terraform apply
これで、terraform apply が実行されるプロセス内でのみ秘密鍵がメモリにロードされ、secrets.sops.yaml が復号されてTerraformに渡されます。平文のキーがディスク上に残ることはありません。
Discussion