Invoke tagging discipline across organization in AWS - 1

<!-- # Invoke tagging discipline across organization in AWS - 1 -->
![haniwa2_tag.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486518/adb53b89-be5f-f1bd-0761-e3d65e3d47ed.png)

組織が多数のAWSアカウントを運用するまでに成長してきますと、組織内のリソースを網羅的に管理したいという意向が出てまいります。

多くのリソースタイプには [タグ](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/Using_Tags.html#tag-basics) がサポートされており、ユーザ固有の管理方針を反映させるのに有用です。しかしこれをいくら徹底させたいといって、要員の自助努力であるとか、性善性に期待するばかりでは不十分なのは容易に想像できます。いくら「徹底」などと口を酸っぱくしたところで結局、めんどくさくなったり、要員が異動するなどし、形骸化してしまうのがオチではないでしょうか。まして複数アカウントですからね。スケーラブルな組織の成長という観点でも、よりスマートな解決策が望まれます。

## AWS は何と言っているか

そこで AWS の公式ドキュメント等に目を向けますと、こういうことが言われております。

(pdf注意)https://d1.awsstatic.com/whitepapers/aws-tagging-best-practices.pdf
> Abstract
> Without the use of tags, it can become difficult to manage your resources effectively as your utilization of AWS services grows. However, it is not always evident how to determine what tags to use and for which types of resources. The goal of this whitepaper is to help you develop a tagging strategy that enables you to manage your AWS resources more effectively.
> タグを利用しないと、AWSサービスの利用が拡大していく中で、リソースを効率的に管理することが難しくなる可能性があります。しかし、どのようなタグをどのような種類のリソースに使用すればよいのか、どのように判断すればよいのか、必ずしも明確ではありません。このホワイトペーパーの目的は、AWSリソースをより効果的に管理できるようなタグ付け戦略の策定を支援することです

https://aws.amazon.com/blogs/aws/new-use-tag-policies-to-manage-tags-across-multiple-aws-accounts/
> Beyond Good Intentions
> All of these tools and recommendations create a strong foundation, and you might start to use tags with only the very best of intentions. However, as **Jeff Bezos, often reminds us, “Good intentions don’t work, but mechanisms do.”** Standardizing on names, values, capitalization, and punctuation is a great idea, but challenging to put in to practice. When tags are used to control access to resources or to divvy up bills, small errors can create big problems!
> 善意を超えて
> これらのツールや推奨事項のすべてが強固な基盤を作り、非常に良い意図だけでタグを使い始めるかもしれません。しかし、ジェフ・ベゾスがよく言っているように、「善意は効かないが、仕組みは効く」のです。名前、値、大文字、句読点を標準化することは素晴らしいアイデアですが、実際に実行するのは難しいことです。タグがリソースへのアクセスを制御したり、請求書を分割したりするために使われている場合、小さなミスが大きな問題を引き起こす可能性があります。

日本語訳は筆者が機械翻訳したものですが、 Good intentions が **善意** と訳されてますね。そして善意に依存しない仕組みが Tag Policies というわけです

## 自組織にどのように導入していくか

企画立案段階で、組織横断チームとして議論の結果得られた合意は次のようなものです

* Tag policies はやはり有効とみられる。入れましょう
* 但し当面は、セキュリティ・ガバナンス専任チームが非準拠情報を **検知** できればよい
  * いきなり問答無用で非準拠オペレーションを **禁止** するとかはちょっとやり過ぎ
  * 禁止等の強い措置は、選択肢として排除はしないが、まずは検知のみで慣熟し、その先の展開は状況をふまえて検討する
* [Security Hub のために以前構成した通知系](https://qiita.com/o2346/items/cd605e9251e234090997) ように、非準拠情報が専用の Slack channel に集約されるのが理想
* 非準拠事案が通知された場合、対象リソースを管轄する開発チームに都度示唆するなど、個別に対応するという運用とする

以前の記事で紹介した、Security Hub の CRITICAL な findings を slack に集約するという仕組みは今のところうまく運用出来ていると思います。 findings が来たら当該チームに remediation を含めて示唆し、解決、というサイクルは概ね確立しております（最初は通知が大量に来てしまい大変でしたが）
そこで今回、 findings をタグ付けルール非準拠事案に置き換え、同様の解決フローを確立できないかと思い立ったわけです。これだと依然として通知から先の対応は人の介在を必要としてしまいますが、個別具体的に非準拠リソースを摘示し、解決を促す仕組みにはなります。直近ではここまでを目標と定め、自動化・厳格化は将来課題とすることにしました

## 導入

では Tag Policies を実際入れていきましょう。 [この手順](https://aws.amazon.com/blogs/aws/new-use-tag-policies-to-manage-tags-across-multiple-aws-accounts/) に沿っていきます。但し当記事では基本的に CLI で進めます

*導入手順は一例のご紹介であり、公式情報と同等の品質は保証致しません。[ベストプラクティスと推奨されるワークフロー](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_tag-policies-best-practices.html) 等に従い、健全な導入体験を心がけましょう。検証専用の Organizations で十分な慣熟をすると安心です*
*Organizations の Master Account での作業です*

### Creating Tag Policies

[enable-policy-type](https://docs.aws.amazon.com/cli/latest/reference/organizations/enable-policy-type.html)

```
aws organizations list-roots --query 'Roots[*].Id' --output text |
  xargs aws organizations enable-policy-type \
    --policy-type TAG_POLICY                 \
    --root-id
```

※次はマスターアカウント側からメンバーアカウント群の準拠情報にアクセスするために必要な設定

```
aws organizations enable-aws-service-access --service-principal tagpolicies.tag.amazonaws.com
```

次のコマンドでは、 [有効な json](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_example-tag-policies.html) ファイルが定義されているものとします

```
aws organizations create-policy                                                      \
  --name "general"                                                                   \
  --description "Tag policy generally supposed to be followed in the organization"   \
  --content file://"organizations/general-tag-policy.json"                           \
  --type TAG_POLICY
```

次で root 直下にあるOU名 `$ou` に `$policy_id` を attach しています。それぞれの有効な値が定義されているものとします

```
aws organizations list-roots --query 'Roots[*].Id' --output text | xargs aws organizations list-organizational-units-for-parent --query 'OrganizationalUnits[?Name==`'$ou'`].Id' --output text --parent-id | xargs aws organizations attach-policy --policy-id $policy_id --target-id
```

### Checking Policy Compliance

```
% aws resourcegroupstaggingapi get-compliance-summary
{
    "SummaryList": [
        {
            "LastUpdated": "2020-12-02T18:50:42Z",
            "NonCompliantResources": 0
        }
    ]
}
```

※次のようなエラーメッセージが出た場合、対策として前掲の `enable-aws-service-access` を実行しましょう

> An error occurred (ConstraintViolationException) when calling the GetComplianceSummary operation: Access to tag policies is not enabled. To enable it, run the AWS Organizations EnableAWSServiceAccess action and specify tagpolicies.tag.amazonaws.com for the service principal.


## おまけ・メンバーアカウントでの確認方法(optional)

前項で指定したOU下に配置されたメンバーアカウントで個別の情報を参照します

次の `PolicyContent` は、Master Account で定義した policy のソースとなっているはずです
*マスターアカウントではなくメンバーアカウントで実行します*

Policy の影響下にあるか確認する

```
% aws organizations describe-effective-policy \
    --policy-type TAG_POLICY
{
    "EffectivePolicy": {
        "PolicyContent": "JSON_STRING_DEFINED_BY_YOURSELF_ON_MASTER_ACCOUNT",
        "TargetId": "111111111111",
        "PolicyType": "TAG_POLICY"
    }
}
```

準拠状況

```
% aws resourcegroupstaggingapi get-resources \
    --include-compliance-details \
    --exclude-compliant-resources
{
    "ResourceTagMappingList": []
}
```

EC2 Instance などに適当なタグを定義してみて、結果を適宜見比べて下さい。非準拠のリソースが存在する場合、その情報が返却されます。上記の実行例では、いずれも非準拠リソースは無いという結果です。

## 次の課題

さて実際やってみてお気づきのかたもいるかもしれませんが、結果の内容をよくよく評価してみますと、「そもそも policy で定義したタグそのものが付与されてもいないリソースは非準拠扱いになっていない」となっている模様です。
ところがこれは [そういう仕様](https://docs.aws.amazon.com/ARG/latest/userguide/tag-policies-arg-finding-noncompliant-tags.html#tag-policy-compliance-account) らしい。
では、あるリソースタイプ（例: EC2 Instance） に全般的網羅的に、指定のタグが付与されていなければいけない、という規則を立案したとして、これを施行するにはどうしたらよいのでしょうか。
Tag policies のコンソールを見てみると、こんなことが書いてあります
> Did you know?
> You can use service control policies (SCPs) with tag policies. You can use SCPs to require tags when creating new resources, and use tag policies to ensure that changes to the tags are always compliant. [Learn more](https://docs.aws.amazon.com/console/organizations/scp-with-tag-policy)

これによると、 Tag policies と並行し、 SCP でタグ自体を要求することができるということらしい。しかしこれだと指定のタグを付与しない限りリソースの作成を禁止までしてしまうという、強い規制となってしまうとみられます。

しかし手前どもの組織で直近で実現させたいのは、非準拠の **検知のみ** なのですよ。将来的に禁止を伴う厳格化を視野に入れているとしても、今直ぐにではありません。
もし厳格化するとすれば、それにあたって各開発チームに遺漏なくその旨周知するとともに、たとえば、これを想定していない既存の CloudFormation テンプレートのアップデート等の検討も必要となる可能性があるからです。ec2 インスタンスで考えてみると、稼働中の [Auto Scaling Group](https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/AutoScalingGroup.html) などにも影響が出るかもしれません。それにもかかわらず唐突に禁止を伴うルールを強制してしまったら問題です。※同じ理由で [enforced_for](https://docs.aws.amazon.com/ja_jp/organizations/latest/userguide/orgs_manage_policies_tag-policies-enforcement.html) の採用も今回は見送っております

ではどうすればよいのか？ SCP のかわりに、 AWS Config のマネージドルール [required-tags](https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/required-tags.html) を併用しようと思います
[次回](https://qiita.com/o2346/items/fd4175335fd78418d9c9) に続きます