AWS Organizationsで組織的にポリシーの管理をしよう

# はじめに

AWS Organizationsを利用することで、複数のアカウントを組織的に管理することが出来ます。

今回、いくつかのプロダクト単位で開発、本番運用を担っている複数のAWSアカウントを持っている。という前提で、AWS Organizationsを利用して、いくつかの問題に対応します。

# 解決したい問題

- 複数AWSアカウントの請求問題
- 複数AWSアカウント間のIAMユーザ切り替え問題
- アカウント単位ではなく、組織的にポリシーを管理したい問題

# 複数AWSアカウントの請求問題

1つのAWSアカウントで、複数のプロダクトを運用している場合もあるとは思いますが、その場合に、まずはプロダクト単位でAWSアカウントを分けることを進めます。
単一のアカウントで運用するのも、複数のアカウントを運用するのも、コスト的な優越はありませんし、プロダクト操作の間違いを防ぐなど、保守性が格段に上がります。

まずはプロダクト単位でAWSアカウントを利用していることを前提に話を進めます。
（もちろん、環境ごとにAWSアカウントを分けることも、保守性はさらに上がりますが、今回は上記の前提で話を進めます。）

さて、プロダクト単位でアカウントを利用する場合、単一のアカウントで運用する場合に比べて、プロダクトを間違ってメンテンナンスをしてしまうというリスクを回避できます（環境ごとにわけると、さらに開発と本番運用によるメンテナンスリスクの回避が出来ます）。

コストによるデメリットはありませんが、AWSアカウントを取得する際に、請求情報を登録する必要があり、請求はAWSアカウント単位に発生します。
この請求ですが、少数のプロダクトを運用しているのであれば、さほど手間にはならないと思いますが、複数のプロダクトを運用する場合には、それぞれで請求が発生すると、請求の煩雑化、または請求漏れ等も把握しにくいのではないかと思われます。

![aws-organizations-ページ9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/b3b0070d-4644-a7b8-a158-80921c4efd89.png)

まずは、この問題を AWS Organizations を利用することで解決しましょう。

### ルートアカウントを作成

まずは、AWS Organizationsの親になるアカウント（**aws-org**）を作成します。既存のAWSアカウントをルートアカウントにしてもいいですが、今回は新規に親となるアカウントを作成します。（アカウント増やすデメリットは個人的にないと思っています。むしろ、このほうがシンプルな構成を作りやすいと思うので、新規でルートアカウントを作ることをおすすめします。）

ここでは、アカウントの作り方は省きます。新規アカウント作成したことを前提に話を進めます。

### 管理者IAMユーザを作成

ルートアカウントにログインしたら、管理者用のIAMユーザを作成します。
ログインしたルートアカウントで作業しても問題はありませんが、推奨はされていません。今回はIAMユーザ（admin）を作成し、AdministratorAccessポリシーもアタッチしたAdminitoratorグループに所属させています。（ポリシーについては、自社の管理者ポリシーに沿って適宜設定してください。）

以下、adminユーザで再ログインしたことを前提で話を進めます。

### 既存アカウントを組織に追加

既存アカウントを組織に追加するために、組織を作成します。
作成方法は、ログインした画面のメニューで 自分のアカウント > マイ組織 を選択し、AWS Organizations で**組織を作成**します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/d939ee02-4107-9e99-f661-c616713736bb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/f47d840b-df30-abf0-01bb-94335ad3dac4.png)

これで組織のルートアカウントを作成することが出来ましたので、次にこの組織にアカウントを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/0a8ec72f-ba1b-b371-7ead-c58210c6ccb7.png)

アカウント追加を選択し、アカウントの招待で、AWSアカウントIDを入力し、招待することで、招待先のAWSアカウントIDのルートアカウントにメール（Title : **Your AWS account has been invited to join an AWS organization**）で通知が行きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/09036a42-5beb-ae0e-c6e4-f354742535fa.png)

メールのリンクから Invitations 画面で 承認（Accept）することで、ルートアカウントの組織に所属します。

**招待先アカウント**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/42ab2b29-d9ce-9acd-f792-f10df1b382a5.png)

**ルートアカウント**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/193a6631-4c4f-1914-481d-236d39546e66.png)

確認としてルートアカウントの請求書のページを確認してみてください。アカウント毎の料金明細が見れるようになっています。
これで、請求が一元管理されていることになります。
（adminユーザでは上記で設定したポリシーでは、請求書を参照する権限はありません。請求書のページはルートアカウントに切り替える必要があります。）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/d2db6575-f33e-8beb-59d4-63261ae6a22b.png)

請求の一元管理をするのはこれだけです。
今回は既存のアカウントを組織に招待する方法を取りましたが、招待する以外に、ルートアカウントから組織に属するAWSアカウントを作成することも可能です。

# 複数AWSアカウント間のIAMユーザ切り替え問題

マネージドコンソールから複数のAWSアカウントを利用する場合、複数のアカウントの切り替える度に、ログインが発生してしまうため、アカウント間の切り替えが非常に手間です。

これはスイッチロールを使うことでアカウント切り替えの手間を軽減することが出来ます。

スイッチロールでは、作成するIAMユーザは全アカウントでひとつで問題ありません（もちろん、ひとつである必要はありません）。

そのIAMユーザが切り替え先のアカウントで操作するために、切り替え先アカウントでは、そのアカウントを利用するためのロールを作成します。
IAMユーザは、切り替え先のアカウントでは、そのロールを使って、そのアカウントを利用することになります。

![aws-organizations-ページ10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/af15b96b-6eac-7113-87c8-c0cbeb0168e4.png)

ルートアカウントで作成したIAMユーザでは、**そのアカウントのロールを利用するためのポリシー**を設定します。
なので、スイッチ先のアカウントでの権限は、ルートアカウントで持っている権限ではなく、そのアカウントのロールに設定されたポリシーに従います。

### スイッチ先アカウントにスイッチロールするためのロールを作成

次の設定は、スイッチ先のロールの設定になります。
ルートアカウントで設定するものではないので、注意が必要です。
招待したアカウントであれば、既にログイン出来るアカウントであると思いますので、IAMの設定が可能なアカウント等で、スイッチ先のアカウントにログインし、IAMのロールの作成へ移動してください。

信頼されたエンティティの種類では、別のAWSアカウントを指定し、このロールを使用できるアカウントでは、ルートアカウントのアカウントIDを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/1b4c2982-f260-265a-03ad-49ed711694c2.png)

今回は、移動先のポリシーを AdministratorAccess で設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/5dfd52fd-8f6c-566d-23c9-b1ac6c36f871.png)

タグの設定はご自由に。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/e8b80f55-512b-b7e4-a10c-06b911f4b15a.png)

ロール名は OrganizationAccountAccessRole とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/a23d648a-cc05-aff3-5b0d-f8b5ad9e1097.png)

スイッチ先のロールの設定は以上です。

ここでスイッチロールのために **OrganizationAccountAccessRole** を作成しましたが、これは今回のケースのように既に存在しているAWSアカウントを招待し追加したためです。
アカウントを招待する際に、アカウントの作成という方法で、新規にルートアカウントに所属するAWSアカウントを作成する手順もあります。
この場合、ここで作成した **OrganizationAccountAccessRole** は、最初から新規AWSアカウントには作成されているので、既にルートアカウントからスイッチロールでアカウントを切り替えることが可能になっています。
ルートアカウントでは、既にadminユーザを作成済みです。
こちらのユーザは、この手順の通りであれば、AdministratorAccessのポリシーがアタッチされているので、スイッチロールでこのアカウントにスイッチすることが可能です。

### スイッチロールでアカウントを切り替える

マネージドコンソールのヘッダーで、アカウント情報からスイッチロールできます。
アカウントIDは、スイッチ先のアカウントID。ロール名は、作成したロール名で、上記の通りであれば **OrganizationAccountAccessRole** です。
表示名、色は任意なので、わかりやすいように設定しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/e59b38f2-7255-0dfa-0788-0f084d8fabe3.png)

ただ、すべてのユーザが admin ユーザでAWSで作業する訳ではありません。むしろしません。
次に、ルートアカウントにユーザを作成し、各アカウントへのスイッチさせるための設定を行います。

### 一般IAMユーザの作成

一般IAMユーザ（dev-user-01、dev-user-02）を作成します。
dev-user-01はすべてのプロジェクトを横断して操作することが可能ですが、dev-user-02は特定のプロジェクト（aws-app-02）のみを操作する権限のみに絞る必要があるとします。
但し、dev-user-01・dev-user-02共に、ルートアカウントのリソースを操作することは出来ません。
今回のケースでは、ルートアカウントは一般IAMユーザにとっては、ログインするためだけのAWSアカウントになります。

![aws-organizations-ページ11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/9005a0b3-ff05-74dc-5439-3cf7176b12db.png)

IAMユーザ自体にポリシーを設定してもいいですが、adminと同様に、グループにユーザを所属させます。
グループは OpsGroupと、Dev02Groupとします。
OpsGroupはすべてのアカウント（ルートアカウント以外）に対して操作する権限を持つグループで、Dev02Groupは aws-app-02 のアカウントにのみ操作する権限を持つグループです。

グループの作成手順については、記載しません。
最終的にグループにアタッチされているポリシーは以下になります。

```json
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": [
      "arn:aws:iam::AWS_APP_01_ACCOUNT_ID:role/OrganizationAccountAccessRole",
      "arn:aws:iam::AWS_APP_02_ACCOUNT_ID:role/OrganizationAccountAccessRole",
      "arn:aws:iam::AWS_APP_03_ACCOUNT_ID:role/OrganizationAccountAccessRole"
    ]
  }
}
```

同様に、Dev02Groupも作成しますが、Dev02Groupにアタッチするポリシーは以下になります。

```json
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": [
      "arn:aws:iam::AWS_APP_02_ACCOUNT_ID:role/OrganizationAccountAccessRole"
    ]
  }
}
```

※ **AWS_APP_xx_ACCOUNT_ID** がそれぞれのAWSアカウントIDになります。

ポリシーについては、あらかじめ上記ポリシーをマネージドポリシーとして作成し、グループ作成時にアタッチしてもいいですし、
グループ作成時にはポリシーはアタッチせず、作成後にインラインポリシーで定義する方法のどちらでも問題ありません。

グループを作成したら、一般IAMユーザを作成し、それぞれのグループに所属させてください。
作成したらスイッチロールで、アカウントを切り替えてみてください。
dev-user-02ユーザで、aws-app-01アカウントに切り替えようとした場合に、以下のように権限がない旨のメッセージが表示され、切り替え出来ないことが確認できると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/7360a9c0-10db-5713-f196-d75ff863f0b9.png)

# アカウント単位ではなく、組織的にポリシーを管理したい問題

AWS Organizations ではポリシーを組織的に管理することできます。
今回、**OrganizationAccountAccessRole** を作成しました。このロールでは、*OrganizationAccountAccessRole* ポリシーをアタッチしているので、ほとんどのサービスを参照することが可能です。
ですので、それぞれのユーザ（グループ）毎に、スイッチするためのロールを作成することで、ユーザ（グループ）単位でサービスへ権限を設定することが可能です。

開発者が増えてくる。管理するプロダクトが増えてくる。
徐々に規模が大きくなるにつれて、いろいろな課題が出てくると思います。
とくにポリシー回りでは、人が増え、グループが増えることで、ルールが煩雑化してしまいがちです。
さらに、管理するプロダクトが増えるとさらに。

AWS Organizationsを利用することで、ポリシーの設定を、アカウント単位から、組織単位に移行し管理することで、煩雑化を軽減していきましょう。

組織を作成した状態である場合、以下で説明する**SCP**、**タグポリシー**が有効となっていません。
まずはそれらを有効にしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/1a2f7bb4-a29a-3da9-4f84-41a4c82333de.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/bc42f876-960f-b146-5369-723cec5d423d.png)

すべての機能を有効化したら、次に各ポリシーを有効化させます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/88e8ee50-6a9f-bc7a-72fd-e70100c26fab.png)

## SCP（サービスコントロールポリシー）で組織のポリシーを設定

まずはAWS Organizationsに所属するアカウントを組織単位に分割します。

![aws-organizations-ページ12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/2d18290f-290c-5e81-29c2-a30aeef9df70.png)

DevOU、OpsOUという組織を作成し、それぞれアカウントをそれぞれの組織に移動します。
この組織単位にポリシーを適用していきます。
例えばOpsOUでは、ログイン出来るIAMユーザの持っているポリシーに関係なく、IAMへの操作を制御したい場合、
アカウントのそれぞれのロールに対して、そのポリシーを付与するのではなく、組織自体に、そのポリシーを付与させます。

これがAWS OrganizationsのSCP（サービスコントロールポリシー）になります。

AWS Organizationsにアカウントを追加した際に、OrganizationAccountAccessRoleを作成しましたが、
組織のポリシーで制御したい場合、このロールに手を加えず、組織のポリシーで制御することで管理することも可能です。

この場合、組織およびIAMユーザのポリシーで許可されているサービスのみが、そのIAMユーザのポリシーになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/6df36d06-e76b-2897-0095-fd63d53e16da.png)

今回は、IAMユーザの作成を組織的に制御するためのSCPを作成する例です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/59b5c00f-6e87-894e-0e34-c4fd77a7e5cf.png)


## タグポリシーでタグの値のゆらぎを排除

もうひとつ。タグのポリシーを組織的に設定することが可能です。
AWSリソースには、独自のタグを付けて管理することが出来ますが、例えば、インスタンスに環境情報を付与し管理したい場合に、タグ名を `env` 。値を `prod` とする人もいれば、`production`、`prd`などと人によってつけ方は様々だったりします。

AWS Organizationsを利用するのであれば、**タグポリシー**を使うことで、特定のタグに対して、有効な値を決めることで、それぞれの命名のゆらぎを排除することが出来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/a545a35f-1413-957d-c329-4d66602028f2.png)

今回はEC2インスタンスのタグに env を設定した際に、有効な値は `dev`、`stg`、`prod` のみを有効するように設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/65a46033-c5d2-36af-735e-ad5b07b3aabc.png)

それでは、このポリシーをアタッチした組織のアカウントで、EC2インスタンスを作成してみましょう。
作成する際に、タグに `env` 値に `staging` としてEC2インスタンスを作成すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297616/6884950f-30cb-ec60-e596-978bf722618a.png)

作成できないことがわかります。

ただ、タグポリシーでは、作成するインスタンスに env タグ自体を付与しない場合には、作成時に警告は出ませんので注意が必要です（こちらの制御は AWS Config を使って出来そうです）。

# さいごに

もともと、請求の管理をまとめるためにAWS Organizationsを調査しました。
それ以外に、今回はポリシーの管理について、手順を含めどのようなことが出来るのかを紹介しましたが、それ以外にも組織的に管理できる機能を利用することが出来ます。
まだまだ調査不足ですが、まずはこのあたりからAWSアカウントを組織的に管理するための整理を、徐々にしていければいいかなと。