Region Restriction via SCP

<!-- # Region Restriction via SCP -->

![Physical_World_Map.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/aa6515bd-b0f5-66b7-d10a-4cb79f816977.png)

今日は [これ](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps_examples.html#examples_general) をやっていきます

まず AWS のリージョンについて
https://aws.amazon.com/jp/about-aws/global-infrastructure/regions_az/
> AWS にはリージョンという概念が存在します。これは、データセンターが集積されている世界中の物理的ロケーションのことです


AWS はアカウント作成時点で [多くの Region がデフォルトで有効となって](https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande-manage.html) おり、追加設定無く利用出来るようになっています（もちろん利用した分だけ請求は来ますが）

世界中のデータセンターから自在にリソースを調達できるのはクラウドの一つの醍醐味。しかしだからといって AWS でデフォルトで有効化されている Regions は数多く、ガバナンスやセキュリティ面から考えると「逆に自在過ぎて心配」になってきたり致します。とくに数十ものメンバーアカウントを抱える Organization ですとなおさらです

例えば「使うのは日本国内と米国東海岸系だけ」といった場合、それ以外の、例えば欧州、カナダ、オーストラリア等は蛇足であるばかりか、放置しておくことで意図しない課金やセキュリティリスクを懸念することになります。
でもいくらセキュリティリスクに対処したいと言って、使いもしない Region なのに Securit Hub 等を入れたりすれば余計な課金や管理負荷が生じてしまい割に合いません。 Region 毎の課金をいちいち監視したりするのもイヤ

そこで「不要なリージョンをそもそも使えないようにさせる」という手段が用意されており、これが [SCP](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps.html) による [Region 規制](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps_examples.html#examples_general) となります。

SCP は Organizations のマスターアカウントで設定し、任意の OU またはメンバーアカウントに対してトップダウンで作用します。この機能を通じてマスターアカウント側から「この操作は禁止」と指定したら、いくらメンバーアカウント側で頑張っても逆らえません。たとえメンバーアカウント側の AdministratorAccess 権限であってもです。規制解除のためにはあくまでもマスターアカウント上で SCP を操作できないといけないので、前述のリスクを排除するための手段として、十分強力だと言えるでしょう

※ ここからは AWS Organizations や SCP について基本的な知識がある前提で進めていきます

## 導入

では早速導入していきます。 次の前提条件が満たされているものとします

* [SCP そのものについて十分理解できていること](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps.html)
  * 先程強力だと書きましたが、 [大いなる力には大いなる責任が伴い](https://en.wikipedia.org/wiki/With_great_power_comes_great_responsibility) ます。 SCP による影響を十分理解・検証した上で適用することをお勧めいたします（とくに本番環境）
* SCP が対象の organization で利用可能になっている

### ポリシーのソースをカスタマイズする

今回は公式の例を少し改造した [こちら](https://github.com/o2346/scp-restrict-regions/tree/custom) を使います
公式との差分は [こちら](https://github.com/o2346/scp-restrict-regions/compare/custom?expand=1#diff-cbd25978ea7487530891398e853978ccf72ad5c3d36402eeccd3be14b1fd3458) です
必要な（=規制対象から除外させたい） Region(s) を明示的に列挙する必要があります。自組織に必要な Region(s) に書き換えましょう

### 施行

あとはこのソースで SCP を [作成](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps_create.html) し [任意の OU またはメンバーアカウントに対してアタッチ](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps_attach.html) するだけ

### 動作確認

試しに対象のメンバーアカウントに管理者権限でアクセスしてみます。
このように規制したい Region(s) でエラー表示が出ていれば成功

![sns_with_an_explicit_deny.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/31e3defb-6e89-b110-af4a-f97be7dfaaca.png)
![ec2_api_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/7ccf8322-5c6c-ad34-c3e0-f36ebd8d3dc1.png)

これと同時に、当然ですが、必要な Region(s) では問題なく操作できなければいけません。規制から除外したリージョン（この場合 us-east-1, ap-northeast-1）にも行き、同様のエラーが出ていないことを確認します
さらに [この辺](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/sample-templates-services-ap-northeast-1.html#w2aac35c38c13c17) の CloudFormation を試しに走らせてみて確かめるとよいでしょう。 [これ](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/new?stackName=ElasticBeanstalkSimple&templateURL=https://s3.ap-northeast-1.amazonaws.com/cloudformation-templates-ap-northeast-1/ElasticBeanstalk_Simple.template) とか [これ](https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/new?stackName=EC2SecurityGroupSample&templateURL=https://s3.ap-northeast-1.amazonaws.com/cloudformation-templates-ap-northeast-1/EC2InstanceWithSecurityGroupSample.template) が丁度いいかもしれませんね

## グローバルサービスを網羅的に列挙する必要がある

実は当組織では最初、 [規制対象外となる Region を書き換えただけで](https://github.com/o2346/scp-restrict-regions/commit/2dfbde7d9af27241263e14630eb5e480b2169d82) 施行していましたが、これだと意図せず AWS Chatbot を規制してしまっていました。原因は [Chatbot がグローバルサービスであった](https://docs.aws.amazon.com/ja_jp/chatbot/latest/adminguide/chatbot-troubleshooting.html) のに、施行した SCP 内の [Statement.NotAction に明示されていなかったから](https://github.com/o2346/scp-restrict-regions/blob/main/redundant-regions-prohibited.json#L7)。施行後、ある開発チームから「AWS Chatbot を使いたいが、エラーが出てしまうので規制解除してほしい」というリクエストが来て気付きました。これを受けて SCP を [アップデート](https://github.com/o2346/scp-restrict-regions/commit/e118ebeeb244742923212f3434513dafd452ca12) したところ解決となりました

## (Optional) AWS SSO Custom permission set で規制をバイパスする

今回施行した SCP では [Statement.Condition.ArnNotLike.aws:PrincipalARN も書き換えて](https://github.com/o2346/scp-restrict-regions/commit/964ba26c437b8787305fd0698add833ed2f17b3d) いますがその理由を説明します

まず、 [ドキュメント](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_scps_examples.html#examples_general) に書いてあるこれですが

> この例では、指定した 2 つの管理者ロールのいずれかによって行われたリクエストを除外する方法も示しています。

これは次の部分が該当するようです

```
 "ArnNotLike": {
                    "aws:PrincipalARN": [
                        "arn:aws:iam::*:role/Role1AllowedToBypassThisSCP",
                        "arn:aws:iam::*:role/Role2AllowedToBypassThisSCP"
                    ]
                }
```

Role1AllowedToBypassThisSCP, Role2AllowedToBypassThisSCP という名称の Role であればこの SCP を回避できることになります（名称がそのまんまですが）

けれどもよくよく考えてみれば、これらの Role さえ作成すれば容易に規制をかいくぐることができてしまう、という重大な注意点にもなるのではないでしょうか。
実際、 Role1AllowedToBypassThisSCP はメンバーアカウント側の権限で任意に作成できてしまいました

![allowed_to_create_bypass_role.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/308bc244-2848-b7e2-b8f1-e76c3c09da9f.png)

せっかく中央集権的に施行した規制なのに、現場サイドに簡単な抜け道を与えてしまっているわけですね。
これを良しとするかは組織の方針にもよりますが、当組織ではこれはなじまない、と判断しました。単純に `Condition.ArnNotLike` を削除してしまう手もありますが、もしかしたら何らかの理由でこの回避策が緊急に必要となる場面もあるかもしれません。そのときになって、一時的に SCP をデタッチするという手もありますが乱暴だし対象が OU だった場合は影響範囲がみだりに広がるし、後でアタッチし直すのを忘れたなどのミスによる影響の大きさも心配です。
要は一応この回避策は留保しつつ、メンバーアカウント側の独断では利用できないように安全にしておきたいわけです。

そこで、 AWS SSO で専用の custom [permission set](https://docs.aws.amazon.com/ja_jp/singlesignon/latest/userguide/permissionsetsconcept.html) を用意し、これに対応する Role 名を指定してはどうかと考えました。 SSO を通じてメンバーアカウント上に自動的に作成される Permission sets 由来の role は、 `arn:aws:iam::*:role/aws-reserved/sso.amazonaws.com/AWSReservedSSO_*` みたいになっており、メンバーアカウントのユーザでは任意作成することができないようです
Permission sets もまた Organizations マスターアカウントの SSO で制御する必要があるため、この名称の role を作成できるのはマスターアカウントだけということになり、メンバーアカウント側からは作成できないはず

AdministratorAccessWRR は筆者が任意に追加した専用の Custom Permission set で、 *Administrator Access Without Region Restriction* のつもりです。この名称は [aws:PrincipalARN で指定したもの](https://github.com/o2346/scp-restrict-regions/blob/custom/redundant-regions-prohibited.json#L59) と一致していれば何でも構いません

![aawrr_permission_set.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/aa2c8d66-2561-9137-5ea2-63e28deacd46.png)

あとはこの Permission set をきちんと管理出来ていれば安心というわけ。ただ今のところは、当組織でこれが必要な状況は直ちには思い浮かびませんので、当面出番は無いかなと思います
※EC2 インスタンスや Lambda Function 等にアタッチする用の非属人的な role も、、となると別途考える必要はありそうですが、基本的な実現方法は今回を通じて理解できましたのでもし必要になったら検討することにします

---

現在 sandbox アカウントでこの SCP を試用していますが、前掲の Chatbot 以外には、とくに問題は聞こえてきません。~~今後、他のアカウント群にも施行していければと考えております~~
*2021/06/15 追記: 対象を 9 アカウント（何れも non-production）に拡大し、引き続き運用中です*