Automation of Terraform for AWS

本投稿は DPE Camp blog series の一部です。

こんにちは。 Platform Infra の Kenichi Sasaki (@siroken3) です。メルカリでは主にAWSの管理を業務にしています。今回の投稿ではAWS構成管理リポジトリのセキュアなCI/CD環境を構築した件について紹介します。

背景

メルカリにおけるAWSの役割

メルカリにおけるAWSの利用の歴史は古く、商品画像を格納するためのストレージとしてS3をサービス開始当初から採用しています。その他S3はMySQLデータベースのバックアップ先、パートナー各社様とのデータ連携のための AWS Transfer Family のバックエンドとして使用しています。また2014年当時のUSメルカリのサービス開始時のメインインフラはAWS上にありました。

直近ではお客さま電話窓口やサポート担当の稼働管理ツールとして Amazon Connect、VDI (Virtual Desktop Infrastructure) として Amazon AppStream 2.0 を導入しています。

これらのサービスはデータの重要度の違いもありアクセスパスを分離するため基本的に各カンパニー、プロジェクト毎に異なるAWS アカウントを作成しています。また、本番環境、開発環境などのソフトウェアライフサイクル別でもAWSアカウントを分けています。さらに開発者個人がPoCできるために個別のAWSアカウントもリクエストに応じて運用しています。これらのアカウントは AWS Organization 配下で管理しています。

課題

これまでメルカリではプロジェクト/カンパニーからのリクエスト毎にAWSアカウントをManagement Consoleを使って人力で作成してきました。またアカウントを作成した後のAWSリソースは HashiCorp Terraform によるIaCで管理してきました。

マイクロサービスほど粒度が小さくはないので、新規に追加されるAWSアカウントが爆発的に数が増えることはなく、運用に支障をきたすことはありませんでした。

しかし、ビジネスが拡大するに従い、新規追加AWSアカウントのリクエストが近い時期に複数発生したりと人力対応をボトルネックとする以下の課題が発生するようになりました。

  • サービス開始までのリードタイムの増加
  • セキュリティ監査のためのログ収集パイプラインを維持管理コストが高くなる

もちろん人力運用における属人性の蓄積も見逃せません。さらに人力によるアカウント作成運用を安定して行うには強い権限を持つ/持つ可能性があるメンバー数を増やさざるを得ません。しかし強権限のユーザを増やすことは異動や退職に伴うセキュリティ上の懸念や運用コストの上昇が発生します。

この課題への対応策の一つはアカウント管理の自動化です。この自動化自体はAWS Organizationの登場以来、AWS自身によって AWS Landing ZoneAWS Control Tower などのソリューションとして提供され拡充してきました。しかし、それらのソリューションの登場当初は既存のOrganizationのアカウントには適用できないなどの事情があり、取り込むタイミングを逃してしまっていました。

一方、メルカリではマイクロサービス構築基盤のGCPにCI/CD基盤が先行して整えられ、各Camp所属のエンジニアのインフラ運用のIaCとしてTerraform、CI/CDは GCPのCloudBuild の利用が進んでいました。

AWSのIaCもTerraformで一部構築されていることもあり、AWSのIaCであるAWS CloudFormation を前提にするAWSのソリューションを直接利用することは社内の普及に難ありと考え一旦見送りました。

Secure CI for AWS in Mercari

これらの課題を踏まえ以下を目標としたセキュアなCI/CD環境(以下Secure CI)の構築を行いました。

  • AWSアカウント作成の自動化
    • TerraformコードPullRequest
  • アカウント作成時ベースライン構築自動化
    • セキュリティ監査ログパイプライン
    • AWS SSO + 社内IDPによる認証認可
  • 高権限奪取リスク低減と影響範囲の局所化
    • 高権限アクセスキーの一時化による攻撃者による奪取リスクをなくす
    • 多層防御として権限を絞ることにより、侵害時の影響範囲を少なくする

Secure CIの構成

全体概要

まず今回構築したメルカリのSecure CI for AWSの全体像を示します(図1)。同図の上半分は GCPの Secure CI と同じ仕組みを再利用していることを示しており、GCPのSecure CIで実現したビルドパイプライン用のYAMLコードをTerraformコードのリポジトリから隔離してオンデマンドでYAMLコードを入手してビルドする仕組みは、このSecure CI for AWSでも実現しています。

これらCloudBuild, Admin Accountは環境 (production, development, laboratory) 毎に作られています。Admin Account とは所属する環境に関連するTerraformのstateファイルを格納するS3 Bucketを持ち、Terraformを実行するIAM Role cross-account-tfm-apply を持っているプロビジョニング専用のAWS Accountです。なお、cross-account-tfm-apply は CloudBuildのServiceAccountを OpenID Connect (OIDC) の IdPとして信頼しています。

この信頼関係によってCloudBuildのビルドパイプラインにおいて恒久的なアクセスキーによるクレデンシャルを用意することなく AWS Security Token Service(STS) の AssumeRoleWithWebIdentity アクションを使いAWSの管理用アカウントのIAM Roleを使うための一時クレデンシャルを用い AWS のリソースを プロビジョニング しています。

したがって、GCPのCloudBuildを使用しているとはいえ、AWSのリソース定義しているterraformのリポジトリは AWS の provider のみ依存しており、CloudBuild以外のビルドパイプラインにも使用できます。

Overview
図1. 全体概要

また、構成するAWSのコンポーネントは以下です。

  • Management account
  • SecurityAudit account
  • Organization Unit (OU)
    • (図では1つですが production, development, laboratory向けに環境毎に存在)
    • Admin account
    • New account
  • AWS Single Sign-On
  • CloudFormation StackSets

以後これらのコンポーネントの役割について目標の実現方法とともに解説します。

AWSアカウント作成自動化

AWSにおいてOrganization内に新たにアカウント(New account)を作るにはOrganizationに唯一存在するManagement account内でCreateAccount APIリクエストをIAM Identity(IAM Roleなど)に発行させる必要があります。Secure CI for AWSにおいては このIAM Roleの役割を cross-account-tfm-apply という名前のIAM Role が担っています。

なおこの cross-account-tfm-apply、CreateAccount APIなどアカウントを作る時のみに必要な権限のみ最小限の権限のみ保持しており、特に STSのAssumeRole権限を持たせていません。理由は後ほど解説します。

New accountが作られた後、TerraformによってリソースをプロビジョニングするためのIAM RoleがNew account内に存在している必要があります。

AWSではOrganizationでアカウントを生成するとAdministrativeなIAM Role (デフォルトではOrganizationAccountAccessRoleという名前)が自動的に作られます。それを利用する方法も考えられました。しかし、このIAM RoleはManagement accountのみ信頼しており、GCPのCloudBuild用のServiceAccountを信頼させるには Management accountを経由した信頼の連鎖をあらかじめ用意しておく必要があります。一方でManagement accountは重要なAccountであり、アカウント新規作成時以外にも本Secure CIを使用するのでできるだけ利用を最小限に留めたいと考えました。

そこで普段のCI/CDで使われるIAM Role(terraform-apply)はOrganizationAccountAccessRole ではなく、AWSから提供されているAccount生成のカスタマイズ手段である CloudFormation StackSets を使用して生成させることにしました。

このCloudFormation StackSetsはDeployment OptionとしてOrganization Unit (OU) を指定できます。この機能を使用してAccountを作ることにしました。この CloudFormation StackSets は名前のとおりCloudFormationでありTerraformではありませんが、ビルドパイプライン内部コンポーネントであり、社内のユーザからは見えないので社内の普及への悪影響はないと考えました。

結果、OU内にNewAccountが作られることをトリガーとして、同Account内のterraform-apply IAM Roleが自動的にそのOUを代表するAdmin accountのみを信頼するよう設定できるようになりました。なお、あらかじめAdmin account は 対応するGCP ProjectをOIDCのIdPとして信頼しています(図2)。

CloudFormationStackSet

図2. OUを代表するAdmin accountを信頼するIAM Roleを自動生成

こうすることでManagement accountを外部に直接晒すことなく、GCPのビルドパイプライン実行に伴う管理用AWS APIリクエストの及ぶ範囲をOrganization Unitの範囲に局所化することができました。なおManagement accountの信頼連鎖と局所化の意義についても後ほど解説します。

セキュリティ監査ログパイプライン構築自動化

メルカリでは各AWSアカウント毎にセキュリティ監査ログ収集の仕組みを構築しています。作成直後のAWSアカウントのベースラインとして提供しています。監査ログ収集のコンポーネントとして特に以下のAWSマネージドサービスを使用しています。

これらは元々一つのTerraform moduleとして社内で利用できるように作成していました。これらはNewAccountが生成されていないと作ることができないため、CloudBuildのパイプラインはアカウントが生成し終わり、CloudFormation StackSets が terraform-apply IAM Role を生成するのを待ち、このTerraform moduleを呼び出しています。

AWS SSO + Okta

メルカリのAWS Management Consoleに対する認証はOktaをSAML identity providerとしたfederation アクセス、またaws-cliの認証は saml2aws を使用してOktaをIdPとした一時クレデンシャルによるアクセスにて実現してきました。

この時ユーザの割り当てはOkta側で行う必要があり、AWSアカウントを作成したあと、Oktaの管理コンソールを利用して人力で行っていました。これも今回の自動化の対象です。
当初 Terraform の Okta provider を使用することを検討してきましたが、Okta API credentialを何らかの方法でproviderに渡さざるを得ず、永続的なクレデンシャルの利用を極力減らしたいというSecure CIの実装方針にそぐわないと考えました。

一方、OktaとAWS Single Sign-On (AWS SSO) の連携がバージョンアップし System for Cross-domain Identity Management (SCIM) v2.0 プロトコルにより、AWS SSOが自動的にIdPであるOktaのuserを取り込み同期する仕組みが構築できるようになり(参考)、これを採用しました。

図3がこの仕組みの概念を表しています。図中右側の User は SCIM v2.0 プロトコルにより、 IdentityStoreUser として自動的に同期されます。左側のオレンジ色の四角はTerraformのリソース等を表しています。PermissionSet は権限、Account はAWSのアカウントを表しており、AccountAssignmentIdentityStoreUserAccount に対しどのPermissionSet の権限を持つかどうかを制御していることを示しています。

AWS SSO and Okta
図3. Okta と AWS SSO の連携

AccountAssignment は AWS のリソースです。よってこれまで説明したAWSのIaCの記述が利用できます。結果、本Secure CIではOkta APIのクレデンシャルは不要となりました。
多層防御として権限を絞り侵害時の影響範囲を少なく
これまでNewAccount 内リソースを プロビジョニングするために terraform-apply IAM Role がterraformのprovider指定でAssumeRoleされることを前提に説明してきました。terraformコードは以下のようになります。

provider “aws” {
   assume_role {
      role_arn = (NewAccount の terraform-apply ARN)
      (略)
   }
}

ここではどのIAM Roleがこのterraformを実行すべきかについて高権限奪取リスクを考慮して検討した内容を説明します。

AWSアカウント作成自動化でも説明しましたが、Organization 配下で作られた全てのAccount に自動的に作られるAdministrativeな権限を持つIAM RoleはデフォルトでManagement account に存在するIAM Identity (IAM User, IAM Role)を信頼しています。よってそのIAM Identityが持つ権限は最小限にする必要があります。

仮にそのIAM IdentityがSTS の AssumeRole 権限を保有しており、かつ悪意のある侵入者がそのIAM Identityを奪取したとします。するとOrganization内の任意のAccountのAdministrative権限を持つIAM RoleにAssumeRoleアクションを用いてなりすますことができてしまうからです(図4)。


図4. Management account に脆弱なIAM Identityがある場合

よってこのIAM Roleはアカウント生成する上で最小限の権限にする必要があり、特にAssumeRole 権限を持たせないようにするため、この章の冒頭で示したTerraformのproviderコードを実行させることができないと考えました。

また、CloudBuildを保持しているGCP Projectは環境毎に作られている一方、Management accountはOrganizationに一つだけ存在する、全環境共通のaccountです。よってManagement accountが直接各環境用の GCP Project をOIDC IdPとして信頼してしまうと、不正目的あるいは意図しないManagement account侵入によるインシデントの入り口を環境数分増やすことになります。

そこで各環境毎に Organization Unit と 代表する Admin account もそれぞれ用意し、Management account にある cross-account-tfm-apply IAM Role は Admin account を経由してCloudBuildを間接的に信頼する形としました(図5)。

Admin account
図5. 環境毎にAdmin account

各AWS Admin account 上の cross-account-tfm-apply IAM Role は所属するOUに対応する GCP Project の ServiceAccount を信頼しています。例えばAdmin account production の cross-account-tfm-apply は GCP CI production のみを信頼しています。

結果、例えば CIのlaboratory環境が奪取されたとしても影響範囲はlaboratory環境のみに局所化できることが期待できます。

今後について

AWSによるアカウント管理の自動化ソリューションである AWS Control Tower の改善はさらに進んでおり、既に既存のOrganizationへの対応が可能になっています。さらに東京リージョンでの利用も可能になりました。IaCコードの問題もAWS製の ControlTower対応 Terraformモジュール が発表され、アカウント作成からセキュリティ監査パイプラインの構築をTerraformと連携させることができるようになりました。

そうすると今回構築したSecure CI for AWSをAWS Control Towerを利用してユーザからみたワークフローを維持したまま置き換えることが現実的になってきています。AWSのマネージドサービスに任せることで運用の手間を減らし、メンテナンス性を向上させることが期待できそうです。

また、今回構築したSecure CI for AWSはGCPに依存しているため、AWSのOrganizationのみで運用させたいユースケースに対応できないため、AWSのみで独立させたいと考えています。

まとめ

本稿では以下について説明しました。

  • メルカリにおけるAWSのユースケース
  • これまでのAWSアカウント管理と必要要件及びその課題
  • GCPとAWSのハイブリッド構成によるCI/CD環境構築の全容
  • 自動化のためのAWSマネージドサービスAWS Control Towerの動向と同サービスを活用した本Secure CI改善の方向性

References

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加