アクセス許可と AWS CDK - AWS Cloud Development Kit (AWS CDK) v2

これは v2 AWS CDK デベロッパーガイドです。古い CDKv1 は 2022 年 6 月 1 日にメンテナンスを開始し、2023 年 6 月 1 日にサポートを終了しました。

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

アクセス許可と AWS CDK

AWS コンストラクトライブラリは、アクセスおよび許可を管理するため、広く実装されている一般的なイディオムをいくつか使用します。IAM モジュールは、これらのイディオムを使用するために必要なツールを提供します。

AWS CDK は AWS CloudFormation を使用して変更をデプロイします。すべてのデプロイには、AWS CloudFormation デプロイを開始するアクター (デベロッパーまたは自動システムのいずれか) が含まれます。これを行う過程で、アクターは 1 つ以上の IAM ID (ユーザーまたはロール) を引き受け、オプションでロールを AWS CloudFormation に渡します。

AWS IAM Identity Center を使用してユーザーとして認証する場合、事前定義された IAM ロールとしてユーザーの行動を許可するため、シングルサインオンプロバイダーは許有効期間の短いセッション認証情報を提供します。AWS CDK が IAM アイデンティティセンター認証から AWS 認証情報を取得する方法については、「AWS SDKs およびツールリファレンスガイド」の「IAM Identity Center 認証を理解する」を参照してください。

プリンシパル

IAM プリンシパルは、AWS API を呼び出すことができるユーザー、サービス、アプリケーションを表す認証された AWS エンティティです。AWS コンストラクトライブラリはプリンシパルを複数の柔軟な方法による指定をサポートし、AWS リソースへのアクセスを許可します。

セキュリティコンテキストでは、「プリンシパル」という用語は特にユーザーなどの認証されたエンティティを指します。グループやロールなどのオブジェクトは、ユーザー (およびその他の認証されたエンティティ) を表すのではなく、アクセス許可を付与する目的で間接的に特定します。

例えば、IAM グループを作成する場合、グループ (およびそのメンバー) に Amazon RDS テーブルへの書き込みアクセスを許可できます。ただし、グループ自体は単一のエンティティを表していないため、プリンシパルではありません (また、グループにログインすることができません)。

CDK の IAM ライブラリでは、プリンシパルを直接または間接的に特定するクラスが IPrincipal インターフェイスを実装するため、これらのオブジェクトをアクセスポリシーで互換的に使用できるようにします。ただし、セキュリティ上の意味ではすべてがプリンシパルではありません。これらのオブジェクトには次のものが含まれます。

  1. RoleUserGroup などの IAM リソース

  2. サービスプリンシパル (new iam.ServicePrincipal('service.amazonaws.com'))

  3. フェデレーティッドプリンシパル (new iam.FederatedPrincipal('cognito-identity.amazonaws.com'))

  4. アカウントプリンシパル (new iam.AccountPrincipal('0123456789012')))

  5. 正規ユーザープリンシパル (new iam.CanonicalUserPrincipal('79a59d[...]7ef2be'))

  6. AWS Organizations プリンシパル (new iam.OrganizationPrincipal('org-id'))

  7. 任意の ARN プリンシパル (new iam.ArnPrincipal(res.arn))

  8. 複数のプリンシパルを信頼するための iam.CompositePrincipal(principal1, principal2, ...)

権限

Amazon S3 バケットや Amazon DynamoDB テーブルなど、アクセスできるリソースを表すすべてのコンストラクトには、別のエンティティにアクセスを許可するメソッドがあります。このようなメソッドのすべては、grant で始まる名前を持ちます。

例えば、Amazon S3 バケットにはエンティティからバケットへの読み取りおよび読み取り/書き込みアクセスをそれぞれ有効にするため、メソッド grantRead および grantReadWrite (Python: grant_read および grant_read_write) があります。エンティティは、これらの操作を実行するために必要な Amazon S3 IAM アクセス許可を正確に知る必要はありません。

付与メソッドの最初の引数は、常に IGrantable 型です。このインターフェイスは、アクセス許可を付与できるエンティティを表します。つまり、IAM オブジェクトの RoleUserGroup などのロールを持つリソースを表します。

他のエンティティにもアクセス許可を付与できます。例えば、このトピックの後半では、CodeBuild プロジェクトにAmazon S3 バケットへのアクセスを許可する方法を示します。一般的に、関連付けられたロールは、アクセスが許可されているエンティティの role プロパティを介して取得されます。

lambda.Function などの実行ロールを使用するリソースも IGrantable を実装するため、ロールにアクセスを許可するのではなく、直接アクセスを許可できます。例えば、bucket が Amazon S3 バケットで function が Lambda 関数である場合、次のコードは関数にバケットへの読み取りアクセスを許可します。

TypeScript
bucket.grantRead(function);
JavaScript
bucket.grantRead(function);
Python
bucket.grant_read(function)
Java
bucket.grantRead(function);
C#
bucket.GrantRead(function);

スタックのデプロイ中にアクセス許可の適用が必要な場合があります。このようなケースのうち、AWS CloudFormationカスタムリソースに他のリソースへのアクセスを許可する例があります。カスタムリソースはデプロイ時に呼び出されるため、デプロイ時に指定されたアクセス許可が必要です。

もう 1 つのケースは、サービスに渡したロールに適切なポリシーが適用されていることをサービスが検証する例です。(ポリシーの設定を忘れないようにするため、多くの AWS サービスがこれを行います) このようなケースでは、アクセス許可の適用が遅すぎる場合、デプロイが失敗する可能性があります。

別のリソースが作成される前に付与されたアクセス許可を強制的に適用するには、こちらに示すように、付与自体に依存関係を追加できます。付与メソッドの戻り値は一般的に破棄されますが、実際にはすべての付与メソッドは iam.Grant オブジェクトを返します。

TypeScript
const grant = bucket.grantRead(lambda); const custom = new CustomResource(...); custom.node.addDependency(grant);
JavaScript
const grant = bucket.grantRead(lambda); const custom = new CustomResource(...); custom.node.addDependency(grant);
Python
grant = bucket.grant_read(function) custom = CustomResource(...) custom.node.add_dependency(grant)
Java
Grant grant = bucket.grantRead(function); CustomResource custom = new CustomResource(...); custom.node.addDependency(grant);
C#
var grant = bucket.GrantRead(function); var custom = new CustomResource(...); custom.node.AddDependency(grant);

ロール

IAM パッケージには、IAM ロールを表す Role コンストラクトが含まれています。次のコードは、Amazon EC2 サービスを信頼する新しいロールを作成します。

TypeScript
import * as iam from 'aws-cdk-lib/aws-iam'; const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), // required });
JavaScript
const iam = require('aws-cdk-lib/aws-iam'); const role = new iam.Role(this, 'Role', { assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com') // required });
Python
import aws_cdk.aws_iam as iam role = iam.Role(self, "Role", assumed_by=iam.ServicePrincipal("ec2.amazonaws.com")) # required
Java
import software.amazon.awscdk.services.iam.Role; import software.amazon.awscdk.services.iam.ServicePrincipal; Role role = Role.Builder.create(this, "Role") .assumedBy(new ServicePrincipal("ec2.amazonaws.com")).build();
C#
using Amazon.CDK.AWS.IAM; var role = new Role(this, "Role", new RoleProps { AssumedBy = new ServicePrincipal("ec2.amazonaws.com"), // required });

ロールの addToPolicy メソッド (Python: add_to_policy) を呼び出し、追加するルールを定義する PolicyStatement で渡すことにより、ロールにアクセス許可を追加できます。ステートメントはロールのデフォルトポリシーに追加されます。持っていない場合、1 つ作成されます。

次の例では、承認されたサービスが AWS CodeBuild であるという条件で、bucket および otherRole (Python: other_role) リソースに ec2:SomeAction および s3:AnotherAction アクションのロールに Deny ポリシーステートメントを追加します。

TypeScript
role.addToPolicy(new iam.PolicyStatement({ effect: iam.Effect.DENY, resources: [bucket.bucketArn, otherRole.roleArn], actions: ['ec2:SomeAction', 's3:AnotherAction'], conditions: {StringEquals: { 'ec2:AuthorizedService': 'codebuild.amazonaws.com', }}}));
JavaScript
role.addToPolicy(new iam.PolicyStatement({ effect: iam.Effect.DENY, resources: [bucket.bucketArn, otherRole.roleArn], actions: ['ec2:SomeAction', 's3:AnotherAction'], conditions: {StringEquals: { 'ec2:AuthorizedService': 'codebuild.amazonaws.com' }}}));
Python
role.add_to_policy(iam.PolicyStatement( effect=iam.Effect.DENY, resources=[bucket.bucket_arn, other_role.role_arn], actions=["ec2:SomeAction", "s3:AnotherAction"], conditions={"StringEquals": { "ec2:AuthorizedService": "codebuild.amazonaws.com"}} ))
Java
role.addToPolicy(PolicyStatement.Builder.create() .effect(Effect.DENY) .resources(Arrays.asList(bucket.getBucketArn(), otherRole.getRoleArn())) .actions(Arrays.asList("ec2:SomeAction", "s3:AnotherAction")) .conditions(java.util.Map.of( // Map.of requires Java 9 or later "StringEquals", java.util.Map.of( "ec2:AuthorizedService", "codebuild.amazonaws.com"))) .build());
C#
role.AddToPolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.DENY, Resources = new string[] { bucket.BucketArn, otherRole.RoleArn }, Actions = new string[] { "ec2:SomeAction", "s3:AnotherAction" }, Conditions = new Dictionary<string, object> { ["StringEquals"] = new Dictionary<string, string> { ["ec2:AuthorizedService"] = "codebuild.amazonaws.com" } } }));

前の例では、addToPolicy (Python: add_to_policy) 呼び出しで新しい PolicyStatement インラインを作成しました。既存のポリシーステートメントまたは変更したポリシーステートメントに渡すこともできます。PolicyStatement オブジェクトにはプリンシパル、リソース、条件、アクションを追加する多数の方法があります。

ロールが正しく機能する必要があるコンストラクトを使用している場合、次のいずれかを実行できます。

  • コンストラクトオブジェクトをインスタンス化するとき、既存のロールに渡します。

  • 適切なサービスプリンシパルを信頼し、コンストラクトに新しいロールを作成させます。次の例では、CodeBuild プロジェクトというコンストラクトを使用します。

TypeScript
import * as codebuild from 'aws-cdk-lib/aws-codebuild'; // imagine roleOrUndefined is a function that might return a Role object // under some conditions, and undefined under other conditions const someRole: iam.IRole | undefined = roleOrUndefined(); const project = new codebuild.Project(this, 'Project', { // if someRole is undefined, the Project creates a new default role, // trusting the codebuild.amazonaws.com service principal role: someRole, });
JavaScript
const codebuild = require('aws-cdk-lib/aws-codebuild'); // imagine roleOrUndefined is a function that might return a Role object // under some conditions, and undefined under other conditions const someRole = roleOrUndefined(); const project = new codebuild.Project(this, 'Project', { // if someRole is undefined, the Project creates a new default role, // trusting the codebuild.amazonaws.com service principal role: someRole });
Python
import aws_cdk.aws_codebuild as codebuild # imagine role_or_none is a function that might return a Role object # under some conditions, and None under other conditions some_role = role_or_none(); project = codebuild.Project(self, "Project", # if role is None, the Project creates a new default role, # trusting the codebuild.amazonaws.com service principal role=some_role)
Java
import software.amazon.awscdk.services.iam.Role; import software.amazon.awscdk.services.codebuild.Project; // imagine roleOrNull is a function that might return a Role object // under some conditions, and null under other conditions Role someRole = roleOrNull(); // if someRole is null, the Project creates a new default role, // trusting the codebuild.amazonaws.com service principal Project project = Project.Builder.create(this, "Project") .role(someRole).build();
C#
using Amazon.CDK.AWS.CodeBuild; // imagine roleOrNull is a function that might return a Role object // under some conditions, and null under other conditions var someRole = roleOrNull(); // if someRole is null, the Project creates a new default role, // trusting the codebuild.amazonaws.com service principal var project = new Project(this, "Project", new ProjectProps { Role = someRole });

オブジェクトが作成されたら、ロール (ロールを渡したが、コンストラクトによってデフォルトのものが作成されたかを問わず) がプロパティ role として利用できます。ただし、このプロパティは外部リソースでは利用できません。したがって、これらのコンストラクトには addToRolePolicy (Python: add_to_role_policy) メソッドがあります。

コンストラクトが外部リソースである場合、メソッドは何も行いません。それ以外の場合は role プロパティの addToPolicy (Python: add_to_policy) メソッドを呼び出します。未定義のケースを明示的に処理する手間を省けます。

次の例で示される内容

TypeScript
// project is imported into the CDK application const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); // project is imported, so project.role is undefined, and this call has no effect project.addToRolePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, // ... and so on defining the policy }));
JavaScript
// project is imported into the CDK application const project = codebuild.Project.fromProjectName(this, 'Project', 'ProjectName'); // project is imported, so project.role is undefined, and this call has no effect project.addToRolePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW // ... and so on defining the policy }));
Python
# project is imported into the CDK application project = codebuild.Project.from_project_name(self, 'Project', 'ProjectName') # project is imported, so project.role is undefined, and this call has no effect project.add_to_role_policy(iam.PolicyStatement( effect=iam.Effect.ALLOW, # ... and so on defining the policy )
Java
// project is imported into the CDK application Project project = Project.fromProjectName(this, "Project", "ProjectName"); // project is imported, so project.getRole() is null, and this call has no effect project.addToRolePolicy(PolicyStatement.Builder.create() .effect(Effect.ALLOW) // .. and so on defining the policy .build();
C#
// project is imported into the CDK application var project = Project.FromProjectName(this, "Project", "ProjectName"); // project is imported, so project.role is null, and this call has no effect project.AddToRolePolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, // ... and so on defining the policy }));

リソースポリシー

Amazon S3 バケットや IAM ロールなど、AWS の一部のリソースにもリソースポリシーがあります。これらのコンストラクトには addToResourcePolicy メソッド (Python: add_to_resource_policy) があり、PolicyStatement を引数として扱います。リソースポリシーに追加されるすべてのポリシーステートメントには、少なくとも 1 つのプリンシパルを指定する必要があります。

次の例では、Amazon S3 バケットbucket が、s3:SomeAction のアクセス許可を持つロールを自らに付与しています。

TypeScript
bucket.addToResourcePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['s3:SomeAction'], resources: [bucket.bucketArn], principals: [role] }));
JavaScript
bucket.addToResourcePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['s3:SomeAction'], resources: [bucket.bucketArn], principals: [role] }));
Python
bucket.add_to_resource_policy(iam.PolicyStatement( effect=iam.Effect.ALLOW, actions=["s3:SomeAction"], resources=[bucket.bucket_arn], principals=role))
Java
bucket.addToResourcePolicy(PolicyStatement.Builder.create() .effect(Effect.ALLOW) .actions(Arrays.asList("s3:SomeAction")) .resources(Arrays.asList(bucket.getBucketArn())) .principals(Arrays.asList(role)) .build());
C#
bucket.AddToResourcePolicy(new PolicyStatement(new PolicyStatementProps { Effect = Effect.ALLOW, Actions = new string[] { "s3:SomeAction" }, Resources = new string[] { bucket.BucketArn }, Principals = new IPrincipal[] { role } }));

外部 IAM オブジェクトの使用

AWS CDK アプリの外部に IAM ユーザー、プリンシパル、グループ、ロールを定義している場合、AWS CDK アプリにその IAM オブジェクトを使用できます。これを行うには、ARN またはその名前を使用してそのリファレンスを作成します。(ユーザー、グループ、ロールの名前を使用します) その後、返されたリファレンスを使用し、前述のようにアクセス許可を付与したり、ポリシーステートメントを構築したりできます。

ポリシー (マネージドポリシーを含む) は、次の方法を使用して同様に使用できます。これらのオブジェクトへのリファレンスは、IAM ポリシーが必要な場所で使用できます。

注記

外部 AWS リソースへのすべての参照と同様に、CDK アプリで外部 IAM オブジェクトを変更することはできません。