シンクロ・フード エンジニアブログ

飲食店.COMを運営する、株式会社シンクロ・フードの技術ブログです

AWS Organizations で複数の AWS アカウントを良い感じに運用する

SRE チームの @fohte です。

今回は、社内インフラ環境の AWS 移行を進めるにあたって課題となった、AWS の権限分割を目的とした AWS Organizations を用いた複数 AWS アカウントの設計や運用の話をします。

AWS Organizations とは

AWS Organizations は、複数の AWS アカウントを一元管理するサービスです。

AWS Organizations には、以下のようなメリットがあります。

  • AWS アカウントの作成・管理が容易になる
  • AWS アカウントごとにポリシーを設定できる
  • 請求が一元管理できる

複数の AWS アカウントを簡単に管理できるようになるため、IAM だけの権限制御と比べ権限管理が圧倒的に楽になります。 Organizations 下であれば AWS アカウントの作成もコマンド一発で行えるようになる 1 ため、気軽に AWS アカウントを分割できるようになります。

また、請求情報もアカウントごとに分離されるため、ネットワークの通信量やリソースの利用料金などがアカウントごとに把握できるようになります。

AWS Organizations 導入前の解決したかった課題

今回 AWS Organizations を導入した最大の目的は、AWS の権限分割です。

最近まで取り組んでいた「社内テスト環境や社内ステージング環境のクラウド移行 (= AWS 移行) プロジェクト」2 の中で、AWS の権限を環境単位で分割したいという要件がありました。 具体的には、「テスト環境は開発者が自由に触れるようにしたいけど、ステージング環境や本番環境は一部制限したい」といった要件です。

実は AWS Organizations 導入前も、本番環境用アカウントと本番以外の環境用アカウントの 2 つのアカウントで運用していました。 しかし、これらのアカウントをテスト環境やステージング環境を構築することは、以下の観点から難しいと判断しました。

  • 本番以外の環境用アカウントは主に開発環境用や AWS の検証環境といった用途で利用している (この上に構築するとどれが何のためのリソースなのか分かりにくくなる)
  • 本番環境用アカウントに構築すると「テスト環境は開発者が自由に触れるようにしたい」という要件が満たせない

そこで、これらの課題を解決できるものとして、AWS Organizations を用いた複数 AWS アカウント運用を選択しました。

AWS アカウント設計

AWS Organizations の導入にあたって、初期段階で悩むことになるのがアカウントの分割単位です。

紆余曲折を経て、現在は以下のようなアカウント構成にしています。

f:id:Fohte:20191203162618p:plain
AWS アカウントの全体像

各アカウントの役割

AWS Organizations Master アカウント

このアカウントではアプリケーション用のリソースは作らず、AWS Organizations の子アカウント管理や CloudTrail での Organizations 下アカウントの監査といった Organizations の管理を行います。

Custodian アカウント

AWS Organizations で複数アカウント運用をするにあたって特に重要となる、IAM ユーザーを一元管理するためのアカウントです。

AWS アカウントが複数個ある場合、アカウントごとに IAM ユーザーを作るのは大変ですし、権限管理も煩雑になります。

そこで、IAM ユーザーはこのアカウントのみ作成するようにし、他アカウントに用意した IAM ロールに Assume Role で切り替えて目的のアカウントを切り替えるようにしています。 これについての詳細は後述します。

アプリケーション用アカウント

前述した「テスト環境は開発者が自由に触れるようにしたいけど、ステージング環境や本番環境は一部制限したい」という要件を満たすために、環境別に用意しているアカウントです。

テスト環境用アカウントでは開発者にも強い権限を設定し、ステージング環境や本番環境用アカウントは弱い権限に設定しています。

また、開発環境用アカウント (Developer Tools) には、開発環境で利用する S3 バケットなどを置いています。

環境間共通アカウント

アプリケーション用アカウントは環境ごとに分離していますが、AMI や ECR リポジトリなどは環境間の差異をなるべく減らすためにも環境間で共有したく、そのようなリソースの置き場として共通アカウントを用意しています。

共通アカウントは目的ごとに作成しており、Operator Tools アカウントに AMI、CD アカウント内に ECR リポジトリや CodeBuild プロジェクトを置いています。

開発者個人用アカウント

開発者が AWS を学習したり検証するための、個別に独立した AWS アカウントを用意しています。 必要に応じて作成しており、開発者はこのアカウントを自由に利用できるようにしています。

Assume Role で簡単にアカウントを切り替える

Assume Role は、任意の IAM ロールを一時的に引き受ける (= assume) ための API です。 「引き受ける」というと想像がつきにくいかもしれませんが、「IAM ロールを移動する (切り替える)」といったイメージです。

以下に示す図のように、Custodian アカウントの IAM ユーザーにユーザー設定のための最小限の権限と Assume Role だけの権限を持たせ、他アカウントでの操作は常に Assume Role で引き受けたロール経由で行うようにしています。

f:id:Fohte:20191204084947p:plain
各アカウントに Assume Role する図

これにより、IAM ユーザーをアカウントごとに用意する必要なく、アカウントの IAM ロールごとに権限制御ができるようになり、権限の分離と簡潔な運用が実現できています。

MFA (多段階認証) を必須化してセキュリティを強固にする

万が一 Custodian アカウントの IAM ユーザーの認証情報が流出してしまう事故が発生したとき、その認証情報だけで他のアカウントのロールに Assume Role できてしまうのは非常に危険です。

その対策として、Assume Role の実行には、AuthyGoogle Authenticator 等を用いた MFA を必須にしています。

具体的には、以下のような IAM ポリシーを全ての IAM ユーザーに設定しています。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::*:role/<role-name>",
      "Condition": {
        "Bool": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}

AWS マネジメントコンソールで Assume Role する

マネジメントコンソールの場合、ヘッダーのユーザーメニュー内にある「スイッチロール」から Assume Role が可能です。

このスイッチロール機能では、過去にスイッチしたロールが 5 件まで表示されるのですが、切り替え先のロールが 6 件以上になってくると大変です。 そういったときは、AWS Extend Switch Roles というブラウザ拡張機能 (Chrome, Firefox) が非常に便利です。 この拡張機能では切り替え先のロールを ~/.aws/config に似たコードで管理でき、マネジメントコンソール上でプロファイル名でのインクリメンタルサーチも可能です。

AWS CLI で Assume Role する

AWS CLI では、aws sts assume-role コマンドで取得できる一時的な認証情報を利用して各種コマンドを実行する必要があります。

これを毎回行うのは手間なので、何らかの Assume Role のラッパー CLI ツールを使うと便利です。 シンクロ・フード社内では、設定やインストールが簡単なことと、MFA に対応していることから aws-vault を推奨しています。

aws-vault では、以下のようなコマンドで MFA を行いつつ Assume Role をした上でコマンドを実行できます。

$ aws-vault exec testing -- aws s3 ...
Enter token for arn:aws:iam::<account-id>:mfa/<username>: (MFA トークンを入力する)

AWS Organizations 導入後の課題

ここまで設計について紹介しましたが、運用が始まってからいくつか課題が出てきました。

全ては紹介しきれませんが、中でも特に課題だと感じている点は、サービスごとのアカウント分離ができていないことです。

前述したように、現在はサービスごとには分離せず、環境ごとにしか分離していません。 しかし、シンクロ・フードではサービスごとのチーム分割が進んでおり、各チームに権限を委譲していくことが重要なテーマになってきています。

そこで、この課題を解決するために、AWS アカウントの分割を始めとした権限分割に今後取り組んでいく予定です。

まとめ

本記事では、シンクロ・フードでの AWS Organizations を用いた複数 AWS アカウントの設計から、Assume Role を駆使した権限管理について紹介しました。

いくつか課題はありますが、AWS Organizations の運用で大きな問題は起こっておらず、安定した運用が実現できていると感じています。

「AWS アカウントを分割したい」、「分割しているけど権限管理がつらい」といった同じ悩みを持った方々の参考になれば幸いです。


  1. aws organizations create-account で AWS アカウントが作成できます。 (create-account — AWS CLI 1.16.298 Command Reference)

  2. このプロジェクトは無事完結しました。プロジェクトの全容は別途記事を公開する予定です。