6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

.env地獄を抜け出した話。SOPS + Age で秘密情報管理が劇的にラクになった件

Last updated at Posted at 2025-12-15

〜Ageと組み合わせて「安全にGit管理」できる最小構成を知る〜

この記事は ZOZO Advent Calendar 2025 の16日目 の記事です。

2025年新卒のじゅんじゅんです。普段はFlutterでのプロダクト開発に従事しています。

はじめに

アプリ開発において必ず向き合うのが APIキー・パスワードなどの秘密情報管理

個人開発などでは .env をSlackで渡してしまったり、
メンバーの誰が最新のやつを持っているか分からなくなることもあります。
さらに、PRレビューでは「どの値が変わったの?」が全く見えず困ったことがある人も多いはず。

そこで今回紹介するのが SOPS + Age

  • 値だけ暗号化して、キー名は残す
  • 暗号化されたまま Gitで扱える
  • 差分レビューがしやすい
  • CI/CDで自動復号できる

この記事では、最短でSOPSを実務に導入できる理解 を目指します。

この記事でわかること

  • SOPSの仕組み:値だけ暗号化し、キー名と構造を保持する理由
  • Ageとの連携方法:公開鍵/秘密鍵を使った暗号化フロー
  • Git運用パターン:差分レビュー、環境別管理、鍵管理
  • CI/CDでの復号方法:GitHub Actionsでの実例

対象読者

経験 レベル
Git 基本操作が分かる
秘密情報管理 .env で苦しんだ経験がある
SOPS 初見でもOK

完成形(イメージ)

SOPSのすごいところは、暗号化後も どのキーが変わったか分かること です。

 api:
-    key: ENC[AES256_GCM,data:old...]
+    key: ENC[AES256_GCM,data:new...]

+    new_token: ENC[AES256_GCM,data:xxx...]  # 新規追加
 database:
-    password: ENC[AES256_GCM,data:before...]
+    password: ENC[AES256_GCM,data:after...]

「値」は暗号化されて見えませんが、キー名は見えるためレビューが非常にしやすい。

👉 デモリポジトリ: https://github.com/junjun-1345/flutter-sops

SOPSとは

SOPS(Secrets OPerationS)YAML / JSON / ENV などの構造を保ったまま値のみ暗号化するツール です。

SOPSの特徴

  • 値だけ暗号化、キー名と構造はそのまま
  • Git管理でも差分レビューしやすい
  • Age / KMS / PGP など複数の暗号方式を選べる
  • VSCodeで復号編集可能

暗号化例

# 暗号化前
api:
  key: my_secret_key
database:
  password: super_secret
# SOPS暗号化後
api:
  key: ENC[AES256_GCM,data:xxx...]
database:
  password: ENC[AES256_GCM,data:yyy...]

「キー名は見える」とは?
値のみ暗号化され、keypassword といった 項目名は残る仕様 のこと。
そのため、PRレビュー時の変更点が把握しやすくなります。

Age + SOPS のセットアップ

インストール

brew install sops age

Age鍵の生成

mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt

出力例:

Public key: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxx

公開鍵は暗号化にのみ利用されるため、漏洩リスクは低く Git 管理しても一般的には問題ありません。
ただし、組織のセキュリティポリシーに従って管理してください。

SOPSが秘密鍵を参照する設定

echo 'export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys.txt"' >> ~/.zshrc
source ~/.zshrc

SOPSの基本的な使い方

1. .sops.yaml をプロジェクトルートに作成

creation_rules:
  - path_regex: .*\.yaml$
    age: age1xxxxxxxxxxxxxxx

2. 平文ファイルを暗号化する

cat > secrets.yaml <<'EOF'
api:
  key: my_secret_key
database:
  password: super_secret
EOF

sops encrypt secrets.yaml > secrets.sops.yaml
rm secrets.yaml

3. 復号化

sops decrypt secrets.sops.yaml

4. 編集(最も便利)

sops secrets.sops.yaml
  • 復号 → 編集 → 再暗号化 を自動で実行

Git差分がなぜ見えるのか?

 api:
     key: ENC[AES256...]
+    new_token: ENC[AES256...]

構造が残るため、どのキーが追加・変更されたか分かります。

SOPS は AES256-GCM を使用しており、一般的に十分安全とされています。
ただし、鍵管理の不備があると安全性は損なわれる ため注意が必要です。

公開鍵と秘密鍵の違い

種類 Git管理 用途
公開鍵 age1xxxx... 暗号化に使用
秘密鍵 AGE-SECRET-KEY-xxxx 不可 復号化に使用

CI/CDでの復号化(GitHub Actions例)

- name: Setup SOPS
  run: |
    mkdir -p ~/.config/sops/age
    echo "${{ secrets.SOPS_AGE_KEY }}" > ~/.config/sops/age/keys.txt

- name: Decrypt secrets
  run: sops decrypt secrets.sops.yaml > config.yaml

※ 復号後のファイル内容をログに出さないよう十分注意してください。

.gitignore

secrets.yaml
config.yaml
keys.txt

実務での運用パターン

1. チームメンバー全員で復号したいケース

creation_rules:
  - path_regex: .*\.yaml$
    age: >-
      age1xxx..., # Aさん
      age1yyy..., # Bさん
      age1zzz...  # CI/CD

2. 環境別ファイル

secrets/
├── dev.sops.yaml
├── stg.sops.yaml
└── prod.sops.yaml

3. 運用フローまとめ

まとめ

  • SOPS + Age は安全に秘密情報を管理しつつGitで扱える
  • 値だけ暗号化してキー名を残す ため差分レビューがしやすい
  • 公開鍵はGit管理可(ただし組織ポリシーに従う)
  • CI/CD まで含めたワークフローがシンプル
6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?