terraform applyをGitHub Actionsで実行してはいけない理由 ― GHAの侵害がAWSの侵害になる構造

目次

「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に寄せられる組織では、こちらもセキュアな選択肢です。

インフラのセキュリティを強化する関連記事

まとめ: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全体の防衛線になります。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次