cdk-nag(python)で特定ルールを対象外（サプレス）とする方法

# はじめに
皆様、AWS CDK（以後、cdk）はご利用されているでしょうか。
AWS公式が出しているIaCということでリソースのアップデートも早く、便利ですよね。
そのcdkのチェックツールとして**cdk-nag**というツールがあります。cdkで作成するリソースがAWSのベストプラクティスなどのルールに則っているかをチェックしてくれるツールです。
（例：S3のバケットはSSEの暗号化がされていること）

https://aws.amazon.com/jp/blogs/news/manage-application-security-and-compliance-with-the-aws-cloud-development-kit-and-cdk-nag/

このcdk-nagはcdk deployコマンドを打つと自動でチェックしてくれますが、どうしても**特定のルールはチェック外にしたい**ということがあると思います。そんなとき、python版のcdk-nagだとどのように記載すればよいかを調査しました。

# やりたいこと
- python版のcdk-nagで、IAM4のルール（AWS管理ポリシーは利用しないこと）をチェックの対象外としたい。
    - [cdk-nagのgithubでのIAM4の説明](https://github.com/cdklabs/cdk-nag/blob/main/RULES.md#awssolutions:~:text=certain%20AWS%20organization.-,AwsSolutions%2DIAM4,-The%20IAM%20user)
- TypeScript版のcdk-nagでの書き方はすぐに見つかる。
    - 参考：https://tech.isid.co.jp/entry/introducing_cdk_nag
- cdkとcdk-nagのバージョンは以下の通り（諸事情によりv2ではありません）。
    - cdk：1.166.1 (build 19c03aa)
    - cdk-nag：1.0.0

# 方法
いきなり結論ですが、以下のような方法でIAM4のルールのチェックを対象外とすることができました。

```python
from aws_cdk import (
    core as cdk,
    aws_lambda as cdk_lambda,
    aws_iam as cdk_iam
)
from cdk_nag import NagSuppressions

# make lambda-role
lambda_role = cdk_iam.Role(self, "lambda-role",
    assumed_by=cdk_iam.ServicePrincipal("lambda.amazonaws.com")
)

# attach managed policies
lambda_role.add_managed_policy(cdk_iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaBasicExecutionRole"))
lambda_role.add_managed_policy(cdk_iam.ManagedPolicy.from_aws_managed_policy_name("service-role/AWSLambdaVPCAccessExecutionRole"))

# cdk-nagのルール除外
NagSuppressions.add_resource_suppressions(lambda_role, [
{ "id": 'AwsSolutions-IAM4', "reason": 'to attach AWS managed policy' }
])
```

ここでは、Lambdaにアタッチするロールを作成して、そこにAWSマネージドポリシーを2つ付与しています。
その状態でcdk deployすると、通常はcdk-nagのチェックが走って、以下のように怒られます。
>[Error at /LambdaRecalculationStack/lambda-recalc-role/Resource] AwsSolutions-IAM4: The IAM user, role, or group uses AWS managed policies. An AWS managed policy is a standalone policy that is created and administered by AWS. Currently, many AWS managed policies do not restrict resource scope. Replace AWS managed policies with system specific (customer) managed policies.

しかし、NagSuppressions.add_resource_suppressions(~)で指定してあげることで例外とすることができます。
（この時、"reason"を10文字以下にするとまた怒られるので注意。しっかり理由は書きましょう。）

# はまったポイント
TypeScriptとpythonでcdk-nagのメソッド名が異なるところではまりました。
cdk-nagのTypeScript版だとこの命令で例外を指定できます。
```typescript
NagSuppressions.addResourceSuppressions(~)
```
ただ、pythonで上記のメソッドを使うと、以下のようにエラーとなります。
```python
AttributeError: type object 'NagSuppressions' has no attribute 'addResourceSuppressions'
```
いやno attributeなわけないやん･･･と色々調べていくと、pythonだと以下のようにアンダーバー(_)で区切るのが正解でした。
```python
NagSuppressions.add_resource_suppressions(~)
```

ちなみに、この情報はpythonの対話モードでattribute情報を出力するdir()を使って調べられました。
```bash
>>> from cdk_nag import NagSuppressions as nag_suppressions
>>> dir(nag_suppressions)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__jsii_declared_type__', '__jsii_type__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'add_resource_suppressions', 'add_resource_suppressions_by_path', 'add_stack_suppressions']
```

# 参考
- cdk-nagのgithub。TypeScriptの情報は完備されている。
https://github.com/cdklabs/cdk-nag/blob/main/API.md

- python版のメソッド名"add_resource_suppressions"でググって1件だけhitしたページ。
https://issueantenna.com/repo/cdklabs/cdk-nag/issues/1013