如何使用CDK创建RDS非特权数据库角色并分发登录凭证
AWS CDK 部署Aurora PostgreSQL时创建非特权数据库账号的实现方案
核心逻辑是将CDK默认生成的集群超级用户凭证的使用范围严格限定在数据库初始化环节,通过自定义资源完成非特权业务账号的创建和权限配置,业务侧服务仅能访问业务账号的凭证,从权限边界上杜绝超级用户凭证泄露风险。
1. 部署基础Aurora集群
首先正常声明PostgreSQL版Aurora集群,保留CDK自动生成的主用户密钥,注意不要将该主密钥的访问权限授予任何业务服务,这个密钥后续仅给数据库初始化逻辑使用。
// 基础集群部署示例(TypeScript) const vpc = ec2.Vpc.fromLookup(this, 'Vpc', { vpcId: 'vpc-xxxxxx' }); const auroraCluster = new rds.DatabaseCluster(this, 'BizAuroraPgCluster', { engine: rds.DatabaseClusterEngine.auroraPostgres({ version: rds.AuroraPostgresEngineVersion.VER_15_4, }), // 自动生成主用户dbadmin的凭证,密钥由Secrets Manager托管 credentials: rds.Credentials.fromGeneratedSecret('dbadmin', { excludeCharacters: '%"\'`@/\\', // 排除容易导致连接转义问题的特殊字符 }), writer: rds.ClusterInstance.provisioned('Writer', { instanceType: ec2.InstanceType.of(ec2.InstanceClass.R6G, ec2.InstanceSize.LARGE), }), vpc, vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, defaultDatabaseName: 'biz_db', });
2. 预创建业务账号的托管密钥
在Secrets Manager中提前生成业务账号的密钥,密钥内自动生成随机密码,后续这个密钥会直接分发给Lambda等业务组件使用。
const bizDbUserSecret = new secretsmanager.Secret(this, 'BizDbUserSecret', { generateSecretString: { secretStringTemplate: JSON.stringify({ username: 'biz_app_user', host: auroraCluster.clusterEndpoint.hostname, port: auroraCluster.clusterEndpoint.port, dbname: 'biz_db', }), generateStringKey: 'password', passwordLength: 16, excludePunctuation: true, }, });
3. 部署自定义资源完成数据库初始化
通过CDK自定义资源(放在和Aurora相同的VPC私有子网中),在集群就绪后自动用主用户凭证连接数据库,执行非特权账号创建、权限分配操作,将预生成密钥中的密码设置为该账号的登录密码。
自定义资源需要绑定的基础权限:
- 主用户密钥的读取权限
- 业务用户密钥的读写权限
- VPC网络访问权限、Aurora集群端口的安全组放行规则
核心执行的SQL逻辑(幂等设计,支持重复部署不报错):
-- 幂等创建业务账号 DO $$ DECLARE app_password text := current_setting('app.biz_user_pwd'); BEGIN IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'biz_app_user') THEN EXECUTE format('CREATE ROLE biz_app_user LOGIN PASSWORD %L', app_password); ELSE EXECUTE format('ALTER ROLE biz_app_user WITH LOGIN PASSWORD %L', app_password); END IF; END $$; -- 按最小权限原则分配权限,以下为普通业务读写账号示例,可按需缩窄 GRANT CONNECT ON DATABASE biz_db TO biz_app_user; GRANT USAGE ON SCHEMA public TO biz_app_user; GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO biz_app_user; GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO biz_app_user; -- 自动给未来新建的表分配对应权限 ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO biz_app_user; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO biz_app_user; -- 显式回收业务账号的高危权限 REVOKE CREATEDB, CREATEROLE, SUPERUSER FROM biz_app_user;
自定义资源需要配置依赖关系,确保集群状态变为可用后再执行初始化逻辑,避免连接失败。
4. 给业务组件授权
给Lambda、ECS等需要访问数据库的业务资源,仅授予业务账号密钥的读取权限,完全不开放主用户密钥的访问入口。
const bizLambda = new lambda.Function(this, 'BizDataLambda', { runtime: lambda.Runtime.NODEJS_20_X, handler: 'index.handler', code: lambda.Code.fromAsset('lambda/dist'), vpc, vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED }, environment: { DB_SECRET_ARN: bizDbUserSecret.secretArn, }, securityGroups: [lambdaSg], }); // 仅授予业务账号密钥的读取权限 bizDbUserSecret.grantRead(bizLambda); // 给Lambda安全组放行Aurora端口访问 auroraCluster.connections.allowDefaultPortFrom(bizLambda);
关键配置要点
- 主用户密钥的访问权限要严格收敛,仅允许数据库初始化资源、紧急运维的IAM角色访问,禁止绑定到任何业务计算资源
- 业务账号的权限严格遵循最小必要原则:只读场景只分配SELECT权限,禁止给业务账号授权SUPERUSER、CREATEROLE、CREATEDB等高危权限
- 可给业务账号密钥配置自动轮转,轮转时触发自定义资源执行改密逻辑,实现凭证全自动轮换无人工介入
- 初始化SQL必须做幂等判断,避免CDK重部署、栈更新时出现重复创建用户的报错
- 自定义资源的执行超时时间建议设置为2分钟,应对Aurora冷启动、网络连接延迟的场景
内容的提问来源于stack exchange,提问作者Isac Casapu
相关产品推荐
相关产品推荐

