📝
memo
CDKプロジェクト初期設定
cdk init app --language typescript
import * as fs from 'fs';
//IAM Access Analyzerで生成したJSON形式のIAMポリシーは policy.json にコピペしておく
//このtsファイルを実行すると、cdkPolicy.tsというファイルが生成されるので、そこに記載されているコードをCDK本体にいい感じにマージする
//IAM Access Analyzerで生成したJSON形式のIAMポリシーをCDKのコードに変換する関数
function convertJsonPolicyToCdkCode(jsonPolicy: any): string {
const policyStatements = jsonPolicy.Statement.map((statement: any) => {
// Actionsが配列でない場合は配列に変換
const actions = statement.Action ? (Array.isArray(statement.Action) ? statement.Action : [statement.Action]) : [];
// NotActionsが配列でない場合は配列に変換
const notActions = statement.NotAction ? (Array.isArray(statement.NotAction) ? statement.NotAction : [statement.NotAction]) : [];
// Resourcesが配列でない場合は配列に変換
const resources = Array.isArray(statement.Resource) ? statement.Resource : [statement.Resource];
// NotResourcesが配列でない場合は配列に変換
const notResources = statement.NotResource ? (Array.isArray(statement.NotResource) ? statement.NotResource : [statement.NotResource]) : [];
// PolicyStatementを生成
let statementCode = ` new iam.PolicyStatement({\n effect: iam.Effect.${statement.Effect.toUpperCase()},\n`;
// actionsが存在する場合のみ追加
if (actions.length > 0) {
statementCode += ` actions: ${JSON.stringify(actions)},\n`;
}
// notActionsが存在する場合のみ追加
if (notActions.length > 0) {
statementCode += ` notActions: ${JSON.stringify(notActions)},\n`;
}
// resourcesが存在する場合は必ず追加
statementCode += ` resources: ${JSON.stringify(resources)},\n`;
// notResourcesが存在する場合のみ追加
if (notResources.length > 0) {
statementCode += ` notResources: ${JSON.stringify(notResources)},\n`;
}
// conditionsが存在する場合のみ追加
if (statement.Condition) {
statementCode += ` conditions: ${JSON.stringify(statement.Condition)},\n`;
}
statementCode += ` })`;
return statementCode;
}).join(',\n ');
// 最終的にManagedPolicyを作成するコードを生成
return `const iamPolicydocument = new iam.PolicyDocument({\n statements: [\n ${policyStatements}\n ]\n});\nconst iamManagedPolicy = new iam.ManagedPolicy(this, 'iamManagedPolicy', {\n document: iamPolicydocument,\n});`;
}
// JSONポリシーをファイルから読み込む
const jsonPolicy = fs.readFileSync('policy.json', 'utf8');
const parsedJsonPolicy = JSON.parse(jsonPolicy);
// CDKコードを生成
const cdkCode = convertJsonPolicyToCdkCode(parsedJsonPolicy);
// 生成されたCDKコードを表示
fs.writeFileSync('cdkPolicy.ts', cdkCode);
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as iam from 'aws-cdk-lib/aws-iam'
import { userInfo } from 'os';
//iam user list
const managerUserNames = ['tom', 'john'];
const contributorUserNames = ['maria', 'sofia'];
export class CdkIamStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
//create iam user group: manager
const iamUserGroupManager = new iam.Group(this, 'iamUserGroupManager', {
groupName: "pan-iam-user-group-manager"
});
//create iam user group: contributor
const iamUserGroupContributor = new iam.Group(this, 'iamUserGroupContributor', {
groupName: "pan-iam-user-group-contributor"
});
//create iam users: manager
const managerUsers: iam.User[] = managerUserNames.map(userName => {
return new iam.User(this, `user-${userName}`, {
userName: userName
});
});
//create iam users: contributor
const contributorUsers: iam.User[] = contributorUserNames.map(userName => {
return new iam.User(this, `user-${userName}`, {
userName: userName
});
});
//create iam role: switch role for manager
const iamRoleManager = new iam.Role(this, 'iamRoleManager', {
assumedBy: new iam.CompositePrincipal(
...managerUsers.map(user => new iam.ArnPrincipal(user.userArn)),
new iam.ServicePrincipal('cloudformation.amazonaws.com')
),
roleName: 'pan-iam-role-switch-manager',
});
//create customer managed policy document: assumerole manager by IAM Access Analyzer
const iamPolicyDocumentAssumeRole = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["sts:AssumeRole"],
resources: [iamRoleManager.roleArn],
})
]
});
const iamManagedPolicyAssumeRoleManager = new iam.ManagedPolicy(this, 'iamManagedPolicyAssumeRoleManager', {
document: iamPolicyDocumentAssumeRole,
});
//create iam role: switch role for contributor
const iamRoleContributor = new iam.Role(this, 'iamRoleContributor', {
assumedBy: new iam.CompositePrincipal(
...contributorUsers.map(user => new iam.ArnPrincipal(user.userArn)),
new iam.ServicePrincipal('cloudformation.amazonaws.com')
),
roleName: 'pan-iam-role-switch-contributor',
});
//create customer managed policy document: assumerole contributor by IAM Access Analyzer
const iamPolicyDocumentAssumeRoleContributor = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["sts:AssumeRole"],
resources: [iamRoleContributor.roleArn],
})
]
});
const iamManagedPolicyAsumeRoleContributor = new iam.ManagedPolicy(this, 'iamManagedPolicyAsumeRoleContributor', {
document: iamPolicyDocumentAssumeRoleContributor,
});
//create customer managed policy document: forceMFA by IAM Access Analyzer
const iamPolicyDocumnetForceMFA = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["iam:GetAccountPasswordPolicy","iam:ListVirtualMFADevices"],
resources: ["*"],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["iam:ChangePassword","iam:Getuser"],
resources: ["arn:aws:iam::*:user/${aws:username}"],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["iam:DeactivateMFADevice","iam:EnableMFADevice","iam:ListMFADevices","iam:ResyncMFADevice"],
resources: ["arn:aws:iam::*:user/${aws:username}"],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["iam:CreateVirtualMFADevice","iam:DeleteVirtualMFADevice"],
resources: ["arn:aws:iam::*:mfa/${aws:username}"],
}),
new iam.PolicyStatement({
effect: iam.Effect.DENY,
notActions: ["iam:CreateVirtualMFADevice","iam:EnableMFADevice","iam:GetUser","iam:ListMFADevices","iam:ListVirtualMFADevices","iam:ResyncMFADevice","sts:GetSessionToken","iam:ChangePassword","iam:CreateLoginProfile","iam:UpdateLoginProfile"],
resources: ["*"],
conditions: {"BoolIfExists":{"aws:MultiFactorAuthPresent":"false"}},
})
]
});
const iamManagedPolicyForceMFA = new iam.ManagedPolicy(this, 'iamManagedPolicyForceMFA', {
document: iamPolicyDocumnetForceMFA,
});
//attach Maneged Policy to group
iamUserGroupManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'));
iamUserGroupManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSBillingConductorFullAccess'));
iamUserGroupManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSCodeCommitFullAccess'));
iamUserGroupManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('IAMFullAccess'));
iamUserGroupManager.addManagedPolicy(iamManagedPolicyForceMFA);
iamUserGroupManager.addManagedPolicy(iamManagedPolicyAssumeRoleManager);
iamUserGroupContributor.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('ReadOnlyAccess'));
iamUserGroupContributor.addManagedPolicy(iamManagedPolicyForceMFA);
iamUserGroupContributor.addManagedPolicy(iamManagedPolicyAsumeRoleContributor);
//attach Managed Policy to Role
iamRoleManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'));
iamRoleManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSBillingConductorFullAccess'));
iamRoleManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSCodeCommitFullAccess'));
iamRoleManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('IAMFullAccess'));
iamRoleContributor.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('ReadOnlyAccess'));
}
}
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as iam from 'aws-cdk-lib/aws-iam'
import { userInfo } from 'os';
//iam user list
const managerUserNames = ['tom', 'john', 'nana'];
const contributorUserNames = ['maria', 'sofia'];
const cdkDeployUserNames = ['renta', 'norenta']
export class CdkIamStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
//ユーザをインポートした際にはタグをつけることはCDKではできない。iam.Userで作成する際にタグを追加する必要がある
/*
// IAMユーザーを作成し、タグを追加
const user = new iam.User(this, 'YamazakiUser', {
userName: 'ymz-manager',
tags: {
'aws/PrincipalTag/CdkDeploy': 'Enable', // タグを指定
},
});
*/
/*
//create cdk user
const CdkDeployUser = new iam.User(this, 'CdkDeployUser', {
userName: 'ymz-cdk-deploy',
})
//タグ付け
cdk.Tags.of(CdkDeployUser).add('aws/PrincipalTag/CdkDeploy', 'Enable');
*/
//create iam user group: cdk
const iamUserGroupCdkDeploy = new iam.Group(this, 'iamUserGroupCdkDeploy', {
groupName: "pan-iam-user-group-cdk"
});
//create iam user group: manager
const iamUserGroupManager = new iam.Group(this, 'iamUserGroupManager', {
groupName: "pan-iam-user-group-manager"
});
//create iam user group: contributor
const iamUserGroupContributor = new iam.Group(this, 'iamUserGroupContributor', {
groupName: "pan-iam-user-group-contributor"
});
//create iam users: manager
const managerUsers: iam.User[] = managerUserNames.map(userName => {
return new iam.User(this, `user-${userName}`, {
userName: userName
});
});
//create iam users: contributor
const contributorUsers: iam.User[] = contributorUserNames.map(userName => {
return new iam.User(this, `user-${userName}`, {
userName: userName
});
});
//create iam users: cdk
const CdkDeployUsers: iam.User[] = cdkDeployUserNames.map(userName => {
return new iam.User(this, `user-${userName}`, {
userName: userName
});
});
CdkDeployUsers.map(user => {
cdk.Tags.of(user).add('CdkDeploy', 'Enable');
})
//create iam role: switch role for manager
//ここ!タグ制御!信頼ポリシーで設定するのが楽
const iamRoleCdkDeploy = new iam.Role(this, 'iamRoleCdkDeploy', {
roleName: 'pan-iam-role-switch-cdk-deploy',
assumedBy: new iam.CompositePrincipal(
...CdkDeployUsers.map(user => new iam.ArnPrincipal(user.userArn).withConditions({
StringLike:{
'aws:RequestTag/CdkDeploy': 'Enable',
},
})),
)
});
//create customer managed policy document: assumerole CDK deplot role
const iamPolicyDocumentAssumeRoleCdkCdployRole = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["sts:AssumeRole"],
resources: [iamRoleCdkDeploy.roleArn],
})
]
});
const iamManagedPolicyAsumeRoloCdkDeploy = new iam.ManagedPolicy(this, 'iamManagedPolicyAsumeRoloCdkDeploy', {
document: iamPolicyDocumentAssumeRoleCdkCdployRole,
});
//create iam role: switch role for manager
const iamRoleManager = new iam.Role(this, 'iamRoleManager', {
assumedBy: new iam.CompositePrincipal(
...managerUsers.map(user => new iam.ArnPrincipal(user.userArn)),
new iam.ServicePrincipal('cloudformation.amazonaws.com')
),
roleName: 'pan-iam-role-switch-manager',
});
//create customer managed policy document: assumerole manager by IAM Access Analyzer
const iamPolicyDocumentAssumeRole = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["sts:AssumeRole"],
resources: [iamRoleManager.roleArn],
})
]
});
const iamManagedPolicyAssumeRoleManager = new iam.ManagedPolicy(this, 'iamManagedPolicyAssumeRoleManager', {
document: iamPolicyDocumentAssumeRole,
});
//create iam role: switch role for contributor
const iamRoleContributor = new iam.Role(this, 'iamRoleContributor', {
assumedBy: new iam.CompositePrincipal(
...contributorUsers.map(user => new iam.ArnPrincipal(user.userArn)),
new iam.ServicePrincipal('cloudformation.amazonaws.com')
),
roleName: 'pan-iam-role-switch-contributor',
});
//create customer managed policy document: assumerole contributor by IAM Access Analyzer
const iamPolicyDocumentAssumeRoleContributor = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["sts:AssumeRole"],
resources: [iamRoleContributor.roleArn],
})
]
});
const iamManagedPolicyAsumeRoleContributor = new iam.ManagedPolicy(this, 'iamManagedPolicyAsumeRoleContributor', {
document: iamPolicyDocumentAssumeRoleContributor,
});
//create customer managed policy document: forceMFA by IAM Access Analyzer
const iamPolicyDocumnetForceMFA = new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["iam:GetAccountPasswordPolicy","iam:ListVirtualMFADevices"],
resources: ["*"],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["iam:ChangePassword","iam:Getuser"],
resources: ["arn:aws:iam::*:user/${aws:username}"],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["iam:DeactivateMFADevice","iam:EnableMFADevice","iam:ListMFADevices","iam:ResyncMFADevice"],
resources: ["arn:aws:iam::*:user/${aws:username}"],
}),
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["iam:CreateVirtualMFADevice","iam:DeleteVirtualMFADevice"],
resources: ["arn:aws:iam::*:mfa/${aws:username}"],
}),
new iam.PolicyStatement({
effect: iam.Effect.DENY,
notActions: ["iam:CreateVirtualMFADevice","iam:EnableMFADevice","iam:GetUser","iam:ListMFADevices","iam:ListVirtualMFADevices","iam:ResyncMFADevice","sts:GetSessionToken","iam:ChangePassword","iam:CreateLoginProfile","iam:UpdateLoginProfile"],
resources: ["*"],
conditions: {"BoolIfExists":{"aws:MultiFactorAuthPresent":"false"}},
})
]
});
const iamManagedPolicyForceMFA = new iam.ManagedPolicy(this, 'iamManagedPolicyForceMFA', {
document: iamPolicyDocumnetForceMFA,
});
//attach Maneged Policy to group
iamUserGroupManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'));
iamUserGroupManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSBillingConductorFullAccess'));
iamUserGroupManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSCodeCommitFullAccess'));
iamUserGroupManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('IAMFullAccess'));
iamUserGroupManager.addManagedPolicy(iamManagedPolicyForceMFA);
iamUserGroupManager.addManagedPolicy(iamManagedPolicyAssumeRoleManager);
iamUserGroupContributor.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('ReadOnlyAccess'));
iamUserGroupContributor.addManagedPolicy(iamManagedPolicyForceMFA);
iamUserGroupContributor.addManagedPolicy(iamManagedPolicyAsumeRoleContributor);
iamUserGroupCdkDeploy.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'));
iamUserGroupCdkDeploy.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSBillingConductorFullAccess'));
iamUserGroupCdkDeploy.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSCodeCommitFullAccess'));
iamUserGroupCdkDeploy.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('IAMFullAccess'));
iamUserGroupCdkDeploy.addManagedPolicy(iamManagedPolicyForceMFA);
iamUserGroupCdkDeploy.addManagedPolicy(iamManagedPolicyAsumeRoloCdkDeploy);
//attach Managed Policy to Role
iamRoleManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AdministratorAccess'));
iamRoleManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSBillingConductorFullAccess'));
iamRoleManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AWSCodeCommitFullAccess'));
iamRoleManager.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('IAMFullAccess'));
iamRoleContributor.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('ReadOnlyAccess'));
}
}
Discussion