「OIDCだから安全」で思考停止していませんか?
GitHub Actions(GHA)でterraform applyを自動実行する構成、使っていませんか? mainにマージされたらGHAがterraform applyを走らせて、インフラが自動で反映される。OIDCでAssumeRoleしているから長期アクセスキーも置いていない。一見まともに見えます。
でもこの構成には、OIDCでは解決できない根本的な問題があります。GHAのジョブが侵害された瞬間、攻撃者がAWSの管理者権限を手にするという構造的な問題です。
本記事では、なぜGHAでterraform applyを実行すべきでないのか、そしてどう対策すべきかを整理します。
なぜGHAでのterraform applyが危険なのか
Terraformの実行には管理者相当の権限が必要
まず前提として、TerraformでAWSインフラを広く管理する場合、実行ロールには実質Admin相当の権限が必要になります。VPC、IAM、RDS、S3、CloudFront、Route 53…管理対象が増えるにつれて、最小権限で設計し続けるコストは現実的ではなくなっていきます。
これはTerraformの欠陥ではなく、「管理者としてインフラを変更するには、管理者相当の権限が必要」という当然の構造です。問題は、その強い権限をどの実行環境に渡すかにあります。
GHAに渡すと何が起きるか
GHAでterraform applyを実行する構成では、そのジョブにAWS管理者相当のIAM Roleを引き受けさせています。OIDCでAssumeRoleしていようが、ジョブの実行中はAWS認証情報が環境変数にセットされ、そのジョブ内の任意のコマンドが同じ権限でAWS APIを叩けます。
【GHAでterraform applyする構成の問題】
GHAジョブが起動
↓
OIDCでAWS管理者相当のRoleをAssumeRole
↓
AWS認証情報が環境変数にセットされる
↓
terraform apply が実行される
↓
しかし同じジョブ内の「任意のコマンド」も同じ権限で動く
↓
ジョブが侵害されたら → 攻撃者がAWS管理者権限を取得OIDCは「認証情報の渡し方」を改善しただけであり、「GHAに強いAWS権限を渡してよいか」とは別の問題です。短期認証情報であっても、ジョブ実行中に攻撃者がAWS APIを呼べれば十分です。
GHAへの攻撃経路は多い
「mainにマージしないと動かないから安全」と思うかもしれません。しかし、GHAの実行環境に到達する経路は想像以上に多く存在します。
- 依存Actionの侵害:使っているサードパーティActionが改ざんされる(tj-actions事件のように)
- 開発者アカウントの侵害:GitHubアカウントやPATが漏洩し、mainへのマージやworkflow実行が可能になる
- PRタイトル・ブランチ名経由のインジェクション:外部から与えられる値をrunステップで不適切に展開するとコマンド実行が成立する
- pull_request_targetの誤用:フォーク元のPRからシークレットにアクセスできる設定になっている
- workflow_dispatch:手動実行できる人の権限設計が甘い
privateリポジトリであっても、外部委託先、連携アプリ、漏洩トークンなど、GHAに到達する経路はいくつもあります。
攻撃者に何ができてしまうか
GHA上で任意コマンド実行が成立し、terraform apply用のAWS権限が取得できた場合、攻撃者は以下のことができます。
- IAM RoleやUserの作成:外部アカウントからAssumeRoleできる信頼ポリシーを追加し、永続的なバックドアを作る
- Security Groupの変更:本来閉じているポートを外部に開放する
- S3 Bucket Policyの変更:機密データを外部からアクセス可能にする
- CloudTrailの無効化:操作ログを消して証拠隠滅する
- Terraformコードの書き換え:applyの前にtfファイルを改ざんし、正常なapplyに見せかけてバックドアを仕込む
つまり、GHAの侵害はCIの侵害ではなく、AWSの管理プレーンの侵害になります。
対策:applyの実行をGHAの外に出す
対策のポイントは、GHAからterraform applyまでを全自動でつなぐことを諦めることです。
GHAは「依頼」だけ、「実行」はAWS側で
GHAの役割を「CodePipelineを起動するだけ」に限定し、実際のterraform applyはAWS側のCodeBuildで実行する構成が有効です。
【推奨構成】
GitHub Actions
↓ codepipeline:StartPipelineExecution(これだけ)
CodePipeline Source
↓
Manual approval(AWS側で手動承認)
↓
CodeBuild で terraform apply(強い権限はここだけ)この構成なら、GHAに渡すAWS権限はcodepipeline:StartPipelineExecutionだけ。Terraform実行に必要な強い権限はCodeBuildのサービスロールに閉じ込められます。GHAが侵害されても、攻撃者ができるのは「パイプラインの起動依頼」まで。実際のapplyにはAWS側の手動承認が必要です。
GitHub Environmentsの承認だけでは不十分
GitHub EnvironmentsのRequired reviewersを使えば、GHA内で承認ステップを挟めます。何もない全自動よりは明らかに安全です。ただし、環境設定、workflowファイル、リポジトリ管理者権限がすべてGitHub内にあるため、GitHub側が侵害された場合は承認を迂回される可能性があります。
terraform applyの承認は、GitHubの外側(AWS側)に置くことで、侵害の境界を分離できます。
HCP Terraformも有力な選択肢
HCP Terraform(旧Terraform Cloud)を使える環境なら、plan後に手動でConfirm & Applyする標準的なフローが用意されています。Terraform実行基盤をHCP Terraformに寄せられる組織では、こちらもセキュアな選択肢です。
インフラのセキュリティを強化する関連記事
- GitHub Actionsのサプライチェーン攻撃を防ぐ!アクションをコミットハッシュで固定する方法 – 依存Actionの侵害対策。SHA pinningとDependabotの連携
- npm install直後にマルウェア感染?パッケージの”即インストール”を今すぐやめるべき理由と設定方法 – サプライチェーン攻撃対策の全般
- IaC(Infrastructure as Code)とは?インフラをコードで管理する3つのメリット – IaCの基本概念とシークレット管理の考え方
- AWS CLIで開発が爆速になる!セットアップからCloudWatch・Lambda活用まで実用コマンド付き – CodePipelineやCodeBuildのCLI操作に
- 「それ、上げちゃダメ!」GitHub管理で絶対守るべきセキュリティルールと対処法 – GitHub側のセキュリティ基本
まとめ:GHAを奪えばAWSを奪える構造を作ってはいけない
- Terraformの実行には管理者相当の権限が必要。これは構造的に避けられない
- GHAでterraform applyすると、その強い権限がGHAのジョブに渡る。ジョブが侵害されたらAWSの管理プレーンが侵害される
- OIDCは認証情報の渡し方を改善するだけ。「GHAに強い権限を渡してよいか」とは別の問題
- GHAへの攻撃経路は多い。依存Actionの侵害、アカウント侵害、インジェクション、pull_request_targetの誤用など
- 対策はapplyの実行をGHAの外に出す。GHAはCodePipelineの起動だけ、applyはAWS側の手動承認後にCodeBuildで実行
GHAで全部自動化するのは便利です。でも、「便利な自動化」と「安全な権限設計」は両立しないことがある。terraform applyのような「インフラ全体を変更できる操作」は、自動化の利便性よりも侵害時の被害半径を優先すべきです。面倒でも、applyの直前にGHAの外で承認を挟む。その一手間が、AWS全体の防衛線になります。
