Настройка ротации паролей Aurora Serverless с использованием CloudFormation (и шаблоны ротации Lambda)

AWS имеет полностью настроенную и готовую к использованию поддержку ротации для некоторых поддерживаемых движков RDS, включая Amazon Aurora (также без сервера?)

Я пытаюсь настроить ротацию пароля в моем шаблоне CloudFormation с помощью AWS::SecretsManager::RotationSchedule (обратите внимание, что это не полностью функциональный шаблон, а только иллюстрация):

  DBCluster:
    Type: AWS::RDS::DBCluster
    Properties:
      Engine        : aurora
      EngineMode    : serverless
      EngineVersion : 5.6.10a

  Secret:
    Type: AWS::SecretsManager::Secret
    Properties:
      GenerateSecretString:
        SecretStringTemplate: '{"username": "admin"}'
        GenerateStringKey: password
        PasswordLength: 20
        ExcludeCharacters: '"@/\'

  SecretTargetAttachment:
    Type: AWS::SecretsManager::SecretTargetAttachment
    Properties:
      SecretId: !Ref Secret
      TargetId: !Ref DBCluster
      TargetType: AWS::RDS::DBCluster

  SecretRotation:
    Type: AWS::SecretsManager::RotationSchedule
    Properties:
      SecretId: !Ref UserAdminSecret
      RotationLambdaARN: <ARN_GET_FROM_SERVERLESS_APPLICATION_REPOSITORY>
      RotationRules:
        AutomaticallyAfterDays: 1

Но функция поворота лямбды AWS не работает со следующим сообщением:

"Движок базы данных должен быть установлен на" mysql ", чтобы использовать эту лямбду вращения": KeyError

Похоже, что Aurora Serverless не поддерживается функцией ротации AWS Lambda, предоставляемой AWS.

Есть ли простой способ настроить секретную ротацию Aurora Server с использованием существующих шаблонов ротации Lambda?

Любой пример, доступный, чтобы написать мою собственную функцию вращения для Aurora Serverless?

PS: Этот вопрос как бы связан с созданием Aurora Serverless Cluster from cloudformation?

1 ответ

Ресурс RotationSchedule зависит от ресурса SecretTargetAttachment. Ресурс вложения обновляет ваше значение секретной строки, чтобы оно содержало информацию о соединении, такую ​​как механизм БД, порт и конечная точка.

К сожалению, CloudFormation не может узнать об этой неявной зависимости между двумя ресурсами. Вам необходимо поместить DependsOn в ресурс RotationSchedule с логическим идентификатором ресурса вложения.

Посмотрите ресурс RotationSchedule в этом примере - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-secretsmanager-rotationschedule.html

Я не использовал бессерверную версию, но получил ту же самую ошибку.

"Ядро базы данных должно быть установлено на mysql, чтобы использовать эту лямбду вращения": KeyError


Решение

Для меня проблема заключалась в том, что мне нужно было предоставить подсети и группу безопасности для лямбда-выражения ротации.

Набросок шаблона CloudFormation будет выглядеть так (обратите внимание на параметры, переданные в лямбду):

DBSecrets:
  Type: AWS::SecretsManager::Secret
  Properties:
    GenerateSecretString:
      SecretStringTemplate: '{"username": "XXXXXXXXXX"}'
      GenerateStringKey: password
      PasswordLength: 24
      ExcludeCharacters: '"@/\'

DBSecretsRDSAttachment:
  Type: AWS::SecretsManager::SecretTargetAttachment
  Properties:
    SecretId: !Ref DBSecrets
    TargetId: !Ref RDSDatabase
    TargetType: AWS::RDS::DBInstance

SecretRotationSchedule:
  Type: AWS::SecretsManager::RotationSchedule
  DependsOn: DBSecretsRDSAttachment
  Properties:
    SecretId: !Ref DBSecrets
    RotationLambdaARN: !GetAtt MySQLRotationLambda.Outputs.RotationLambdaARN
    RotationRules:
      AutomaticallyAfterDays: 30

MySQLRotationLambda:
  Type: AWS::Serverless::Application
  Properties:
    Location:
      ApplicationId: <ARN_GET_FROM_SERVERLESS_APPLICATION_REPOSITORY>
      SemanticVersion: 1.1.0
    Parameters:
      endpoint: !Sub 'https://secretsmanager.${AWS::Region}.amazonaws.com'
      functionName: <Function Name>
      vpcSubnetIds: <Comma delimited List of VPC subnet IDs>
      vpcSecurityGroupIds: <Comma delimited List of VPC security grouop IDs>

RDSDatabase:
  Type: AWS::RDS::DBInstance
  Properties:
    MasterUsername: !Sub '{{resolve:secretsmanager:${DBSecrets}::username}}'
    MasterUserPassword: !Sub '{{resolve:secretsmanager:${DBSecrets}::password}}'
    Engine: mysql
    DBSubnetGroupName: <Your Subnet Group>
    VPCSecurityGroups: <Your Security Group>

Почему отображается эта ошибка?

Лямбда вращения проходит следующие этапы:

  • Сначала попробуйте войти в систему с ожидающим секретом, если это удастся, верните
  • Теперь попробуйте текущий пароль
  • Если и текущий, и ожидающий не работают, попробуйте предыдущий

Ему не удается войти в систему с ожидающим и текущим секретом, затем происходит сбой с этой ошибкой при попытке использовать предыдущий секрет. Ожидающий и текущий секрет действительны, Lambda просто не может подключиться к базе данных. Предыдущий секрет - это секрет, который вы изначально указываете в шаблоне CloudFormation выше.

{
  "username": "XXXXXXXXXX", 
  "password": "XXXXXXXXXX"
}

В AWS::SecretsManager::SecretTargetAttachment изменяет его на правильный формат (для RDS MySQL Single User):

{
  "engine": "mysql",
  "host": "<required: instance host name/resolvable DNS name>",
  "username": "<required: username>",
  "password": "<required: password>",
  "dbname": "<optional: database name. If not specified, defaults to None>",
  "port": "<optional: TCP port number. If not specified, defaults to 3306>"
}

Вложенный стек поворота Lambda имеет больше параметров, которые вы можете передать, просто посмотрите его шаблон на панели управления CloudFormation.

Мне удалось настроить ротацию секретов для Aurora Serverless с помощью AWS Fully Configured and Ready-to-Use Rotation Support: aws-secrets-manager-rotation-lambdas/SecretsManagerRDSPostgreSQLRotationSingleUser/

Я получал ту же ошибку, что и в Q выше, я обнаружил, что в моих секретах установка "engine": "postgres"настройка отсутствовала. После добавления настройки, как показано ниже, он начал работать

{
  "username": "XXXX",
  "password": "XXXXXXXXXX",
  "engine": "postgres",
  "host": "db.cluster-XXXX.us-XXXX-X.rds.amazonaws.com",
  "port": 5432,
  "dbClusterIdentifier": "XXXXX"
}

Я столкнулся с аналогичной ошибкой при настройке параметров PostgreSQL "password_encryption: 'scram-sha-256'"

Решением было отказаться от воссоздания всего стека CloudFormation с помощью MD5. (Обновление значения не устранило ошибку)

Кроме того, если у Lambdalog есть тайм-аут без других ошибок, увеличьте таймаут лямбда-функции по умолчанию с 30 секунд до 60 секунд, чтобы решить проблему.