前回は GitHub Actions で Python スクリプトを定期実行する方法(スケジュール実行・手動トリガー)を紹介しました。今回はいよいよ「本番っぽい運用」に踏み込む回です。テーマは シークレット管理 と 自動デプロイ。AWS の認証情報や API キーをどう安全に扱うか、というやつです。
正直、最初はこのあたりが一番よくわからなかった。ワークフローファイルは GitHub 上で丸見えなのに、どこに秘密情報を書けばいいのか…という混乱があって。調べていくうちにだいぶ整理できたので、まとめておきます。
- GitHub Actions のシークレットの種類(Repository / Environment / Organization)と使い分け
- Repository Secrets・Environment Secrets の具体的な設定手順
- Python スクリプトでの環境変数の受け取り方
- AWS Lambda への自動デプロイワークフローの実装例
- シークレットを安全に扱うための注意点(echo 禁止・Variables との混同など)
GitHub Actions のシークレット管理、何が違う?
まず基本の整理から。GitHub Actions でシークレットを扱う方法は大きく3種類あります。
- Repository Secrets:リポジトリ全体で使えるシークレット
- Environment Secrets:特定の環境(production / staging など)に紐づいたシークレット
- Organization Secrets:Organization 配下の複数リポジトリで共有できるシークレット
個人開発だと Repository Secrets だけで済むことが多いんですが、「本番環境には本番用の API キー、ステージングには別のキーを使いたい」みたいなケースが出てくると Environment Secrets が便利です。
シークレットは組織・リポジトリ・リポジトリ環境の単位で保存できます。GitHub Actions でシークレットを使うには、ワークフローファイル内で明示的に参照(環境変数やアクションの input に受け渡し)する必要があります。
Environment Secrets では、環境保護ルールとして「必須レビュアー(required reviewers)」を設定でき、承認が下りるまではその環境のシークレットにジョブがアクセスできない、という制御も可能になります。チームだとだいぶ助かるやつです。
Repository Secrets の設定手順
まずは Repository Secrets から。設定場所はリポジトリの Settings です。
「Settings」タブを開き、サイドバーの「Security」セクションから「Secrets and variables」→「Actions」を選択し、「Secrets」タブをクリックして登録できます。
ここで AWS_ACCESS_KEY_ID や OPENAI_API_KEY などを登録しておきます。値は一度保存すると二度と見えません(本当に見えない)。
ワークフローから参照するには ${{ secrets.シークレット名 }} という構文を使います。
name: Deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: pip install -r requirements.txt
- name: Run deploy script
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
run: python deploy.py
Python 側では普通に os.environ で取得できます。
import os
api_key = os.environ["OPENAI_API_KEY"]
webhook_url = os.environ.get("SLACK_WEBHOOK_URL", "")
ちなみに env: ブロックはステップ単位で書くのが原則です。ジョブ全体に env: を設定することもできますが、スコープを絞った方が安全。最小権限の原則はワークフロー内でも意識したい。
Environment Secrets で dev / prod を切り替える
次に Environment Secrets のパターンです。たとえば「main ブランチへの push は production 環境にデプロイ、develop ブランチは staging に」という構成を作りたいとき。
まず GitHub 側で Environment を作成します。Settings → Environments → New environment で production と staging を作り、それぞれ別のシークレットを登録しておきます。
ワークフローでは environment: キーを指定するだけです。
jobs:
deploy-prod:
runs-on: ubuntu-latest
environment: production # ここで環境を指定
steps:
- uses: actions/checkout@v4
- name: Deploy
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: python deploy.py
Environment Secrets にアクセスするには、設定された保護ルール(必須レビュアーなど)をすべてクリアする必要があります。
なお、Environment 自体や Environment Secrets は GitHub Pro / Team のプライベートリポジトリでも利用可能 です。一方で「必須レビュアー(required reviewers)」「wait timer」などの 一部のデプロイ保護ルールは、プライベートリポジトリでは Enterprise 以外だと使えないケースがあります(公開リポジトリだと無料で使えることもある)。プランとリポジトリ公開範囲で挙動が変わるので、ここだけは実際に Settings の画面で項目が出るか確認するのが確実です。
リポジトリシークレットはワークフロー横断で共有したい値に、Environment Secrets はデプロイ先ごとに異なるシークレット(例:dev/prod で別の API トークン)に使い分けるのが基本的な考え方です。
AWS デプロイの実装例(Lambda へのデプロイ)
具体例として、Python スクリプトを AWS Lambda にデプロイするワークフローを書いてみます。第1回・第2回でスケジュール実行や通知の仕組みを作ってきたので、その延長です。
AWS 認証には aws-actions/configure-aws-credentials を使います。
name: Deploy to Lambda
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
pip install -r requirements.txt -t ./package
cp lambda_function.py ./package/
- name: Zip package
run: cd package && zip -r ../deploy.zip .
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Deploy to Lambda
run: |
aws lambda update-function-code \
--function-name my-function \
--zip-file fileb://deploy.zip
依存ライブラリを -t ./package で同じディレクトリに展開して zip にまとめるのが Lambda デプロイのお作法です。最初これがわからなくてけっこうハマりました。
OIDC 認証という選択肢も
余談ですが、最近は AWS 認証を長期的なアクセスキー(AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY)ではなく、OIDC トークンで行う方法も広まっています。
OIDC を使うと、GitHub Actions ワークフローから AWS リソースにアクセスする際に、長期間有効な AWS クレデンシャルを GitHub Secrets に保存する必要がなくなります。「長期の AWS アクセスキーを GitHub Secrets に置かなくて済む」というのが主なメリットで、クレデンシャルを長期間有効な状態で複製し続けなくていい、という考え方です。
ワークフロー側では permissions: id-token: write を追加して、configure-aws-credentials アクションに role-to-assume を渡す形になります。セキュリティ的にはこちらが理想なんですが、IAM Role(+ OIDC Provider)の設定が必要で少し手間があります。個人的にはまだアクセスキー方式で運用していて、OIDC への移行は「次のリファクタリングでやろう」と思い続けてそれなりの時間が経っています。
シークレットを安全に扱うための注意点
最後に、やらかしがちなポイントをいくつか。
echo でシークレットをログに出さない
GitHub Actions はシークレットの値をログにマスクしてくれますが、マスクは万能ではないです。たとえば、値を加工(base64 化したり、一部だけ切り出したり、JSON から取り出した値にしたり)すると、マスク対象から外れて漏れることがあります。なので echo ${{ secrets.SOMETHING }} は書かないのが原則です。
# NG
- run: echo "KEY=${{ secrets.API_KEY }}"
# OK: env 経由で渡してスクリプト内で使う
- run: python check.py
env:
API_KEY: ${{ secrets.API_KEY }}
Secrets と Variables を混同しない
シークレットとは別に「Variables」(vars.xxx)という機能もあります。こちらは秘匿性のない設定値(リージョン名・関数名など)を管理するためのもので、ログにも普通に表示されます。API キーを Variables に入れてしまうとそれだけで終わりなので、絶対に間違えないようにしましょう(見た目が似てるので油断すると混同します)。
フォークされたリポジトリからのアクセス
フォークされた PR からのワークフロー実行では、デフォルトでシークレットが渡されません。これは意図的な仕様で、悪意ある PR でシークレットを抜かれないようにするためです。オープンソースプロジェクトで CI を組む場合は特に意識しておいた方がいいです。
※この記事にはプロモーションが含まれます
ちなみに、お名前.com レンタルサーバー(WordPressに特化した高速レンタルサーバー。月額990円〜、独自ドメイン実質0円)も気になっています。お名前.com レンタルサーバー![]()
まとめ
シークレット管理は「とりあえず Repository Secrets に入れておけば動く」というレベルから始めて、デプロイ先が複数になってきたら Environment Secrets を活用する、という流れが自然だと思います。OIDC は理想的ではあるけど、個人開発のうちはアクセスキー方式でも十分かなと(ちゃんとローテーションするという前提で)。
- Repository Secrets:まず覚えるべき基本。個人開発はほぼこれで完結
- Environment Secrets:dev / prod で異なるキーを使いたくなったら導入
- OIDC 認証:セキュリティを突き詰めたいなら検討。ただし IAM 設定が必要
- Variables との混同:API キーを Variables に入れない。これだけは絶対
そういえば最近、Actions の設定画面がちょいちょい変わってて「昨日と同じ場所に無い…」みたいなことが起きがちです。こういうの、地味に体力削られます。
📚 シリーズ「GitHub Actions × Python 自動化入門」(第3回 / 全4回)
← 前回の記事: 前回の記事はこちら
→ 次回の記事: 【第4回】GitHub Actions × Python 自動化入門 — ワークフロー設計のベストプラクティスとよくあるハマりどころ
関連記事
→ 次回の記事: 【第4回】GitHub Actions × Python 自動化入門 — ワークフロー設計のベストプラクティスとよくあるハマりどころ

