You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Typescript CDK自定义Lambda实现Secrets Manager密钥每小时轮转

基于Typescript CDK实现IAM用户密钥每小时自动轮转方案

1. 前置依赖安装

先安装所需的CDK依赖包:

npm install @aws-cdk/aws-secretsmanager @aws-cdk/aws-lambda-nodejs @aws-cdk/aws-iam @aws-cdk/core

2. 编写自定义轮转Lambda代码

在项目根目录新建lambda/rotate-iam-user-password.ts文件,代码遵循Secrets Manager官方约定的4步轮转接口规范:

import { SecretsManager, IAM } from 'aws-sdk';
const secretsManager = new SecretsManager();
const iam = new IAM();

interface RotationEvent {
  SecretId: string;
  ClientRequestToken: string;
  Step: 'createSecret' | 'setSecret' | 'testSecret' | 'finishSecret';
}

export const handler = async (event: RotationEvent) => {
  const { SecretId, ClientRequestToken, Step } = event;

  switch (Step) {
    case 'createSecret':
      // 生成新密码并存入待生效版本
      await secretsManager.putSecretValue({
        SecretId,
        ClientRequestToken,
        SecretString: JSON.stringify({
          username: 'user',
          password: generateRandomPassword()
        }),
        VersionStages: ['AWSPENDING']
      }).promise();
      break;

    case 'setSecret':
      // 获取待生效密码,同步更新IAM用户密码
      const pendingSecret = await secretsManager.getSecretValue({
        SecretId,
        VersionStage: 'AWSPENDING',
        VersionId: ClientRequestToken
      }).promise();
      const { password } = JSON.parse(pendingSecret.SecretString as string);
      await iam.updateLoginProfile({
        UserName: 'user',
        Password: password,
        PasswordResetRequired: false
      }).promise();
      break;

    case 'testSecret':
      // 可自行补充新密码有效性验证逻辑
      break;

    case 'finishSecret':
      // 将新密码版本标记为当前生效版本
      const secretDesc = await secretsManager.describeSecret({ SecretId }).promise();
      const currentVersionId = Object.entries(secretDesc.VersionIdsToStages || {})
        .find(([_, stages]) => stages.includes('AWSCURRENT'))?.[0];
      await secretsManager.updateSecretVersionStage({
        SecretId,
        VersionStage: 'AWSCURRENT',
        MoveToVersionId: ClientRequestToken,
        RemoveFromVersionId: currentVersionId
      }).promise();
      break;
  }
};

// 生成符合IAM密码策略的随机密码,可根据需求调整规则
function generateRandomPassword(): string {
  const length = 16;
  const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=';
  let password = '';
  for (let i = 0; i < length; i++) {
    password += charset.charAt(Math.floor(Math.random() * charset.length));
  }
  return password;
}

3. 更新CDK栈配置

补充你现有代码的轮转相关配置:

import * as cdk from '@aws-cdk/core';
import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
import * as iam from '@aws-cdk/aws-iam';
import * as lambda from '@aws-cdk/aws-lambda-nodejs';
import { Duration } from '@aws-cdk/core';

export class YourStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const templatedSecret = new secretsmanager.Secret(this, 'TemplatedSecret', {
      generateSecretString: {
        secretStringTemplate: JSON.stringify({ username: 'user' }),
        generateStringKey: 'password',
      },
    });

    const otherUser = new iam.User(this, 'OtherUser', {
      userName: templatedSecret.secretValueFromJson('username').unsafeUnwrap(),
      password: templatedSecret.secretValueFromJson('password'),
    });

    // 部署轮转Lambda函数
    const rotationLambda = new lambda.NodejsFunction(this, 'RotationLambda', {
      entry: 'lambda/rotate-iam-user-password.ts',
      handler: 'handler',
      runtime: lambda.Runtime.NODEJS_18_X,
      timeout: Duration.seconds(30)
    });

    // 授予Lambda必要的操作权限
    templatedSecret.grantRead(rotationLambda);
    templatedSecret.grantWrite(rotationLambda);
    otherUser.grant(rotationLambda, 'iam:UpdateLoginProfile');

    // 配置每小时自动轮转规则
    templatedSecret.addRotationSchedule('RotationSchedule', {
      rotationLambda,
      automaticallyAfter: Duration.hours(1)
    });
  }
}

注意事项

  • Lambda代码中的用户名user需和实际创建的IAM用户名保持一致,避免密码同步失败
  • 可根据企业IAM密码策略调整generateRandomPassword函数的密码生成规则
  • 生产环境建议在testSecret步骤补充实际的密码有效性验证逻辑,确认新密码可正常使用后再标记为生效
  • 不要在CDK代码中对敏感值使用toString(),建议使用unsafeUnwrap()获取动态引用,避免敏感值泄露到部署配置文件中

内容的提问来源于stack exchange,提问作者Gulshan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 20:24:04