GitHub Actions再利用可能ワークフローでEnvironment Secretsが予想外に使える話

GitHub Actions再利用可能ワークフローでEnvironment Secretsが予想外に使える話

初めに

ども!最近はどんな検証をするときも最後のデプロイまで作るので、GitHub Actionsをセットで書くことが多い龍ちゃんです。今回はGitHub Actionsの再利用可能ワークフローについてお話ししたいと思います。最近、同じリポジトリ内でCIのワークフローからCDのワークフローを呼び出す際に、GitHubのシークレットがうまく渡せない問題に遭遇しました。

特に興味深いのが、公式ドキュメントでは「Environment Secretsは渡せない」とされているのに、実際にはなぜか渡ってしまうという現象です。この予想外の動作について検証した結果をご紹介します。

実際に試してみませんか?
この記事で紹介した検証は、皆さんのGitHubリポジトリでも再現できます。特に「公式ドキュメントでは不可能とされているが実際には動作する」という部分は、実際に動かしてみることで納得感が得られると思います。ぜひ検証してみて、結果をコメントで教えていただけると嬉しいです!
というか!GitHub公式のドキュメントにケチつける内容なんで自信がないんです!!

GitHub Secretsには3つのパターンがある

まずは基本から整理しましょう。GitHubのシークレットには3つの設定パターンがあります。

Secret種別設定レベルアクセス範囲主な用途特徴
Repository Secretsリポジトリ全てのワークフローAPIキー、一般的な設定値基本的なシークレット管理
Organization Secrets組織複数リポジトリで共有組織共通の認証情報組織レベルでの統一管理
Environment Secrets環境特定環境のみデプロイ先の機密情報承認フロー、ブランチ制限と連携

それぞれセキュリティレベルと管理範囲が異なるため、プロジェクトの要件に応じて使い分ける必要があります。

再利用可能ワークフローについて

再利用可能ワークフローは、DRY原則でワークフローを共通化できる機能です。基本的な使い方はこんな感じです:

jobs:
  deploy:
    uses: ./.github/workflows/reusable.yml

メリットとしては、メンテナンス性向上、標準化、コード重複削減が挙げられます。2022年5月にsecrets: inheritという機能も追加されて、より使いやすくなりました。

公式ドキュメントによる制限事項

公式ドキュメントでは、以下のような記載があります:

“Environment secrets cannot be passed from the caller workflow as on.workflow_call does not support the environment keyword”

つまり、想定される動作は:

  • Repository/Organization Secrets → ✅ 継承可能
  • Environment Secrets → ❌ 継承不可

これが開発者の困りごとでした。デプロイワークフローでEnvironment Secretsを使いたいし、環境ごとの承認フローも維持したい。しかし再利用可能ワークフローでは使えない、という状況です。

実際の検証: 段階的にSecret継承を確認

Repository/Organization Secrets の検証(期待通りの動作)

まず確実に動作するパターンから見ていきましょう。

name: ci-repo-org-secrets-tests

on:
  workflow_dispatch:

jobs:
  # API_KEYはrepoかorgにKEYが設定されている必要がある
  call-secrets:
    uses: ./.github/workflows/cd-secrets-mapped.yml
    secrets:
      API_KEY: ${{ secrets.API_KEY }}
 
  call-secrets-inherit:
    uses: ./.github/workflows/cd-secrets-mapped.yml
    secrets: inherit

再利用可能ワークフロー側:

name: cd-secrets

on:
  workflow_call:
    secrets:
      api_key:
        required: true

jobs:
  deploy-job:
    runs-on: ubuntu-22.04
    name: Get to GitHub Secret
    steps:
      - name: Check Validation Result
        run: |
          echo "🔍 デプロイ前検証を実行中..."
          if [ -z "${{ secrets.api_key }}" ]; then
            echo "::error title=Missing Deployment Target::api_key が必要です"
            exit 1
          fi

結果: 両パターンとも正常動作。公式ドキュメント通りの動作を確認できました。

Environment Secrets の検証(予想外の動作)

検証環境の準備として、Environment: productionを作成し、Environment Secret: API_KEYを設定しました。再利用可能ワークフローはjobレベルでしか呼び出せないので、Secretで明示的に渡す方法がありません。

検証パターン2-A: secrets: inherit なし(動作しない)

name: ci-env-secrets-tests

on:
  workflow_dispatch:
    inputs:
      env_name:
        description: "Environment name to test (e.g. production, staging)"
        required: true
        default: "production"
        type: environment

jobs:
  # 失敗する(これは納得)
  call-env-fixed-no-inherit:
    uses: ./.github/workflows/cd-env-fixed.yml

  # 成功する(なぜ!?)
  call-env-fixed-inherit:
    uses: ./.github/workflows/cd-env-fixed.yml
    secrets: inherit

再利用可能ワークフロー側:

name: cd-env-fixed

on:
  workflow_call:

jobs:
  deploy:
    runs-on: ubuntu-22.04
    # 呼び出される側で環境を固定する例(ここでは production)
    environment: production
    steps:
      - name: Mask and check environment secret
        run: |
          echo "🔍 Environment 'production' で環境シークレットを検証"
          echo "::add-mask::${{ secrets.API_KEY }}"
          if [ -z "${{ secrets.API_KEY }}" ]; then
            echo "::error title=Missing API_KEY::Environment 'production' の API_KEY が未設定です"
            exit 1
          fi
          echo "✅ Environment 'production' のシークレット(API_KEY)を参照できました(値はマスク済み)"

実行すると、inheritを付けたパターンは成功し、付けていないパターンは失敗します。

検証結果の整理

Secret種別明示的指定secrets: inherit公式見解からの理解実際の動作
Repository渡せる✅ 動作
Organization渡せる✅ 動作
Environment渡せない🚨 動作する

コミュニティでの議論状況

この問題は2021年から指摘されていますが、現在でも修正されていないようです。

主要なIssue

  • Issue #1490 (2021年11月): 最初に問題が報告された「Environment Secrets are not available on Reusable Workflow」
  • Issue #3379 (2024年7月): 現在も続く問題への要望「Enhancement: Streamlining secret inheritance to environment in reusable workflows」

3年間解決されていない状況で、バグなのか仕様なのかが不明です。多くの開発者が同様の問題で混乱しており、コミュニティではsecrets: inherit + 再利用可能ワークフロー側でのenvironment指定という回避策が使われています。

「使えるけど公式サポートではない」という微妙な状態が続いています。

実用的な活用方法

現在使える推奨パターンは以下の通りです:

# 呼び出し側
jobs:
  deploy:
    uses: ./.github/workflows/deploy.yml
    secrets: inherit

# 再利用可能ワークフロー側
jobs:
  deploy-job:
    runs-on: ubuntu-latest
    environment: production  # ここで環境を指定(inputで渡すこともできるよ!)
    steps:
      - name: Deploy
        run: echo "Deploy with ${{ secrets.DEPLOY_KEY }}"

セキュリティ考慮事項

  • 意図しないSecretが渡されるリスクがある
  • Environmentの承認フローは正常に機能する
  • Repository/Organization Secretsも同時に渡される点に注意が必要

代替手法の比較

  • Repository Secrets: 管理が簡単だがセキュリティレベルが低い
  • Organization Secrets: スケールするがすべてのリポジトリからアクセス可能
  • 専用キー管理サービス: 最もセキュアだが複雑性が増す

プロジェクトでの判断基準としては、環境ごとのデプロイ制御が必要な場合は現在の回避策を使用し、セキュリティ要件が厳しい場合は専用サービスを検討するのが良いでしょう。将来の公式サポートを見据えた設計にしておくことも重要です。

まとめと今後の展望

現状の整理をすると:

  • Environment Secretsはsecrets: inheritで実際には使える
  • 公式ドキュメントと実装に乖離があるように見える(公式の記載の理解ができていないのかも…)
  • 3年間この状態が続いている

シークレットが意図せず渡せてしまう状況は便利に使えますが、個人的には、リポジトリ単位でのキー管理方法や、専用のキー管理サービス(キーボールトなど)を使うべきではないかと考えるようになってしまいました。

現在の方法を理解した上で慎重に活用し、セキュリティリスクを十分検討した上で、GitHubの動向を継続的にウォッチしていくことが重要ですね。この検証はマジで疲れました!


参考リンク

公式ドキュメント

コミュニティの議論

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です