はじめに
皆様、AWS CDK(以後、cdk)はご利用されているでしょうか。
AWS公式が出しているIaCということでリソースのアップデートも早く、便利ですよね。
そのcdkのチェックツールとしてcdk-nagというツールがあります。cdkで作成するリソースがAWSのベストプラクティスなどのルールに則っているかをチェックしてくれるツールです。
(例:S3のバケットはSSEの暗号化がされていること)
このcdk-nagはcdk deployコマンドを打つと自動でチェックしてくれますが、どうしても特定のルールはチェック外にしたいということがあると思います。そんなとき、python版のcdk-nagだとどのように記載すればよいかを調査しました。
やりたいこと
- python版のcdk-nagで、IAM4のルール(AWS管理ポリシーは利用しないこと)をチェックの対象外としたい。
- TypeScript版のcdk-nagでの書き方はすぐに見つかる。
- cdkとcdk-nagのバージョンは以下の通り(諸事情によりv2ではありません)。
- cdk:1.166.1 (build 19c03aa)
- cdk-nag:1.0.0
方法
いきなり結論ですが、以下のような方法でIAM4のルールのチェックを対象外とすることができました。
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版だとこの命令で例外を指定できます。
NagSuppressions.addResourceSuppressions(~)
ただ、pythonで上記のメソッドを使うと、以下のようにエラーとなります。
AttributeError: type object 'NagSuppressions' has no attribute 'addResourceSuppressions'
いやno attributeなわけないやん・・・と色々調べていくと、pythonだと以下のようにアンダーバー(_)で区切るのが正解でした。
NagSuppressions.add_resource_suppressions(~)
ちなみに、この情報はpythonの対話モードでattribute情報を出力するdir()を使って調べられました。
>>> 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