AWS CDK 100 实战练习 #002:IAM 基础 —— 用户、角色与安全密码管理
发布: (2025年12月10日 GMT+8 00:00)
6 min read
原文: Dev.to
Source: Dev.to
介绍
这是 AWS CDK 100 Drill Exercises 系列的第二个练习。
想了解更多关于该系列,请参阅这篇介绍文章。
在学习了第一个练习中的 S3 基础后,我们现在深入 AWS 身份与访问管理 (IAM)。IAM 是 AWS 安全的基石,负责控制谁可以访问你的资源以及他们可以对资源执行的操作。
为什么在 S3 之后学习 IAM?
- 安全基石 – IAM 对所有 AWS 资源的安全至关重要。
- 真实需求 – 每个 AWS 部署都需要恰当的访问管理。
- CDK 集成 – 了解 CDK 如何生成 IAM 策略和角色。
- 最佳实践 – 从一开始就学习安全模式,可防止未来的漏洞。
你将学到的内容
- CDK 如何创建 IAM 用户、组和角色。
- 使用 AWS Secrets Manager 进行安全密码管理。
- 托管策略与内联策略的区别。
- 带 MFA 要求的切换角色实现。
- CloudFormation 的动态密钥解析。
- IAM 安全最佳实践。
📁 代码仓库:所有示例均可在GitHub上获取。
架构概览
我们将在四个构造体中实现六种不同的模式。
构造体 1:基础用户 (CDKDefaultUser)
- 模式 1 – 最小化的 IAM 用户配置。
构造体 2:密码管理用户 (IAMUserWithPassword)
- 模式 2A – 硬编码密码(⚠️ 不推荐)。
- 模式 2B – 使用 Secrets Manager 的安全密码管理(✅ 推荐)。
- 模式 3A – 附加 AWS 托管策略。
- 模式 3B – 附加内联策略。
构造体 3:组管理用户 (IamUserGroup)
- 模式 4 – 基于组的权限管理。
构造体 4:切换角色用户 (SwitchRoleUser)
- 模式 5 – 需要 MFA 的角色假设。
前置条件
- 已安装并配置 AWS CLI v2。
- Node.js 20+。
- AWS CDK CLI(
npm install -g aws-cdk)。 - 基础的 TypeScript 知识。
- AWS 账户(免费套餐即可)。
- 对 IAM 概念(用户、角色、策略)有基本了解。
项目目录结构
iam-basics/
├── bin/
│ └── iam-basics.ts # 应用入口点
├── lib/
│ ├── stacks/
│ │ └── iam-basics-stack.ts # 主栈定义
│ └── constructs/
│ ├── iam-user-with-password.ts # 模式 2‑3
│ ├── iam-user-with-group.ts # 模式 4
│ └── iam-user-with-switch-role.ts # 模式 5
├── test/
│ ├── compliance/
│ │ └── cdk-nag.test.ts # 测试(后文解释)
│ ├── snapshot/
│ │ └── snapshot.test.ts # 测试(后文解释)
│ └── unit/
│ └── iam-basics.test.ts # 测试(后文解释)
├── cdk.json
├── package.json
└── tsconfig.json
模式 1:了解 CDK 默认用户
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as iam from 'aws-cdk-lib/aws-iam';
export class IamBasicsStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// 最小化的 IAM 用户配置
const cdkDefaultUser = new iam.User(this, 'CDKDefaultUser', {});
}
}
生成的 CloudFormation
{
"Resources": {
"CDKDefaultUserF7AAA71A": {
"Type": "AWS::IAM::User",
"Metadata": {
"aws:cdk:path": "Dev/DrillexercisesIamBasics/CDKDefaultUser/Resource"
}
}
}
}
默认配置细节
- 用户名 – 由 AWS 自动生成。
- 密码 – 无;默认情况下禁用控制台访问。
- 策略 – 没有任何权限(最小特权原则)。
- 访问密钥 – 无;默认禁用编程访问。
在显式授予权限之前,该用户无法访问任何资源。
模式 2A:带硬编码密码的用户(⚠️ 不推荐)
⚠️ 此模式演示在生产环境中硬编码密码的危险性。
const userWithPassword = new iam.User(this, 'PasswordUser', {
password: cdk.SecretValue.unsafePlainText('InitialPassword123!'),
passwordResetRequired: true,
});
生成的 CloudFormation
{
"UserWithPasswordPasswordUserA5E8EDB8": {
"Type": "AWS::IAM::User",
"Properties": {
"LoginProfile": {
"Password": "InitialPassword123!",
"PasswordResetRequired": true
}
}
}
}
为什么这很危险
- 密码写在源码中 – 在版本控制中可见。
- CloudFormation 模板 – 密码会在控制台和日志中暴露。
- 未加密 – 以明文形式存储。
- 审计追踪 – 难以追踪密码的变更。
切勿在生产环境中使用此模式。
模式 2B:使用 Secrets Manager 的用户(✅ 推荐)
import * as secretsmanager from 'aws-cdk-lib/aws-secretsmanager';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as cdk from 'aws-cdk-lib';
const userName = 'SecretsPasswordUser';
// 创建包含自动生成密码的密钥
const userSecret = new secretsmanager.Secret(this, 'UserSecret', {
generateSecretString: {
secretStringTemplate: JSON.stringify({ username: userName }),
generateStringKey: 'password',
excludePunctuation: true,
passwordLength: 16,
requireEachIncludedType: true,
},
});
// 使用 Secrets Manager 中的密码创建 IAM 用户
const user = new iam.User(this, 'SecretsPasswordUser', {
userName: userName,
password: userSecret.secretValueFromJson('password'),
passwordResetRequired: true,
});
// 附加允许用户自行更改密码的 AWS 托管策略
user.addManagedPolicy(
iam.ManagedPolicy.fromAwsManagedPolicyName('IAMUserChangePassword')
);
这种做法将密码安全地存储在 Secrets Manager 中,避免了硬编码机密,并且在需要时可以实现密码轮换。