[AWS Secrets Manager] SecretsManager CloudFormation으로 작성해보기!

Classmethod Korea Co., Ltd.
Classmethod Korea Co., Ltd.
12 min readJun 7, 2022

소개

안녕하세요! 클래스메소드 금상원 입니다. 이번 블로그에서는 SecretsManager를 CloudFormation을 이용하여 작성하는 방법에 대해 해보도록 하겠습니다.

콘솔 화면에서 SecretsManager작성 하는 방법에 대하여

https://blog.naver.com/classmethodkr/222708266217

SecretsManager작성하기

SecretString JSON 에 램덤으로 생산되는 패스워드를 가진 새로운 SecretsManager를 작성합니다.

이 정보에는 암호, 사용자 이름 및 암호와 같은 자격 증명 집합, OAuth 토큰 또는 Secrets Manager에서 암호화된 형식으로 정보를 저장 합니다.

RDSRotationSecret: 
Type: AWS::SecretsManager::Secret
Properties:
Description: "test rds instance secret"
Name: "/aws/rds/cluster/test/keum"
GenerateSecretString:
SecretStringTemplate: '{"username": "admin"}'
GenerateStringKey: "password"
PasswordLength: 32
ExcludeCharacters: '"@/\'

GenerateSecretString : 비밀번호를 생성하고 SecretsManager에 저장하는 방법을 지정하는 구조입니다.

SecretStringTemplate : 생성된 문자열이 RDS와 일치되여야하는 부분이기때문에 RDS의 MasterUsername을 입력해줍니다.

GenerateStringKey : 키/값 쌍의 JSON 키 이름입니다. 여기서 값은 생성된 RDS의 비밀번호입니다.

PasswordLength : 비밀번호의 길이를 지정합니다.

ExcludeCharacters : 암호에 포함하지 않는 문자를 지정합니다. (문제가 되는 문자들을 주로 기입합니다.)

RDS와 연결하기

RDS와 생성한 SecretsManager를 연결하여 해당 RDS의 비밀번호를 관리 합니다.

SecretRDSInstanceAttachment:
Type: AWS::SecretsManager::SecretTargetAttachment
Properties:
SecretId: !Ref RDSRotationSecret
TargetId: !Ref RDSCluster
TargetType: AWS::RDS::DBCluster

SecretId : 생성된 SecretsManager의 ID를 입력합니다. (!Ref를 사용하는 것을 추천합니다.)

TargetId : 연결할 서비스의 ID를 입력합니다. (!Ref나 !ImportValue를 사용하는 것을 추천합니다.)

TargetType : 연결할 서비스의 유형을 링크 에서 확인 후 입력합니다.

로테이션 작성하기

보안 암호에 대한 교체 일정 및 Lambda 교체 함수를 설정합니다.

MySecretRotationSchedule:
Type: AWS::SecretsManager::RotationSchedule
DependsOn: SecretRDSInstanceAttachment
Properties:
SecretId: !Ref RDSRotationSecret
HostedRotationLambda:
RotationType: "PostgreSQLSingleUser"
RotationLambdaName: "SecretsManagerRotation"
VpcSecurityGroupIds: !ImportValue SMSG
VpcSubnetIds: "subnet-bb293dd2"
RotationRules:
Duration: "1h"
ScheduleExpression: "cron(0 17 ? * FRI *)"

SecretId : 로테이션을 연결할 SecretsManager의 ID를 입력합니다. (!Ref를 사용하는 것을 추천합니다.)

HostedRotationLambda : Secrets Manager 교체 함수 템플릿 중 하나를 기반으로 새 Lambda 교체 함수를 생성합니다 .

RotationType : 회전 기능의 기반이 되는 회전 템플릿을 링크에서 확인한 후 입력 해주세요.

VpcSecurityGroupIds : 람다에 사용할 보안그룹ID을 입력합니다.

VpcSubnetIds : 람다를 배치할 Subnet의 ID를 입력합니다.

RotationRules : Secrets Manager에 대한 Rotation 구성을 정의하는 구조입니다.

Duration : Rotation을 실행하는 시간의 길이입니다. Secrets Manager는 이 기간 동안 언제든지 암호를 교체합니다.

ScheduleExpression : 암호 교체 일정을 정의합니다. 표현식은 cron()또는 rate() 사용합니다.

전체 코드

AWSTemplateFormatVersion: "2010-09-09"
Description: "Secrets Manager with automatic rotation"
Transform: "AWS::SecretsManager-2020-07-23"
Parameters:
USERNAME:
Type: String
Default: "keum"
Description: user name
DBNAME:
Type: String
Default: "test"
Description: DB Name
DBTYPE:
Type: String
Default: "db.r6g.large"
Description: DB Instance Type
ENGINE:
Type: String
Default: "aurora-postgresql"
Description: DB Engine
ENGINEVERSION:
Type: String
Default: "13.5"
Description: DB Engine Version
Resources: RDSRotationSecret:
Type: AWS::SecretsManager::Secret
Properties:
Description: "test rds instance secret"
Name: "/aws/rds/cluster/test-prd-db-rds-aurora-postgresql/okina"
GenerateSecretString:
SecretStringTemplate: '{"username": "keum"}'
GenerateStringKey: "password"
PasswordLength: 32
ExcludeCharacters: '"@/\'
RDSClusterParameterGroup:
Type: "AWS::RDS::DBClusterParameterGroup"
Properties:
Description: "DB Parameter Group for test-prd-db-rds-aurora-postgresql"
Family: "aurora-postgresql13"
Parameters:
timezone : Asia/Tokyo
client_encoding: UTF8
Tags:
- Key: Name
Value: "test-prd-db-rds-aurora-postgresql-cluster-dbparametergroup"
DBSubnetGroup:
Type: AWS::RDS::DBSubnetGroup
Properties:
DBSubnetGroupDescription: "DB Subnet Group on Isolated Subnets"
DBSubnetGroupName: "test-prd-rds-sbng"
SubnetIds:
- !ImportValue PrivateSubnet-a #from subnet.yaml
- !ImportValue PrivateSubnet-c #from subnet.yaml
Tags:
- Key: Name
Value: "test-prd-rds-sbng"
RDSCluster:
Type: AWS::RDS::DBCluster
Properties:
DatabaseName: !Ref DBNAME
Engine: !Ref ENGINE
EngineMode: "provisioned"
EngineVersion: !Ref ENGINEVERSION
DBClusterIdentifier: "test-prd-db-rds-aurora-postgresql"
MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref RDSRotationSecret, ':SecretString:username}}' ]]
MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref RDSRotationSecret, ':SecretString:password}}' ]]
DBSubnetGroupName: !Ref DBSubnetGroup
Port: 5432
BackupRetentionPeriod: 7
CopyTagsToSnapshot: true
PreferredBackupWindow: "16:00-16:30"
PreferredMaintenanceWindow: "Fri:18:00-Fri:18:30"
DeletionProtection: true
EnableCloudwatchLogsExports:
- postgresql
VpcSecurityGroupIds:
- !ImportValue RDSSG
DBClusterParameterGroupName: !Ref RDSClusterParameterGroup
StorageEncrypted: true
RDSDBParameterGroup:
Type: "AWS::RDS::DBParameterGroup"
Properties:
Description: "DB Parameter Group for test-prd-db-rds-aurora-postgresql"
Family: "aurora-postgresql13"
Tags:
- Key: Name
Value: "test-prd-db-rds-aurora-postgresql-dbparametergroup"
RDSDBInstance:
Type: "AWS::RDS::DBInstance"
Properties:
DBClusterIdentifier: !Ref RDSCluster
DBInstanceClass: !Ref DBTYPE
MultiAZ: false
AvailabilityZone: "ap-northeast-1a"
PubliclyAccessible: false
EnablePerformanceInsights: true
PerformanceInsightsRetentionPeriod: 7
AutoMinorVersionUpgrade: true
PreferredMaintenanceWindow: "Fri:18:30-Fri:19:00"
DBSubnetGroupName: !Ref DBSubnetGroup
DBParameterGroupName: !Ref RDSDBParameterGroup
Engine: !Ref ENGINE
EngineVersion: !Ref ENGINEVERSION
SecretRDSInstanceAttachment:
Type: AWS::SecretsManager::SecretTargetAttachment
Properties:
SecretId: !Ref RDSRotationSecret
TargetId: !Ref RDSCluster
TargetType: AWS::RDS::DBCluster
MySecretRotationSchedule:
Type: AWS::SecretsManager::RotationSchedule
DependsOn: SecretRDSInstanceAttachment
Properties:
SecretId: !Ref RDSRotationSecret
HostedRotationLambda:
RotationType: "PostgreSQLSingleUser"
RotationLambdaName: "SecretsManagerRotation"
VpcSecurityGroupIds: !ImportValue SMSG # from sg.yaml
VpcSubnetIds: "subnet-bb293dd2" # ec2 subnet
RotationRules:
Duration: "1h"
ScheduleExpression: "cron(0 17 ? * FRI *)"

마무리

이번 블로그에서는 CloudFormation을 이용하여 AWS ScretsManager를 작성하는 방법에 대해 알아보았습니다.

ScretsManager를 CloudFormation으로 작성 하실려는 분들에게 조금이나마 도움이 되었으면 좋겠습니다.

클래스메소드코리아에 문의사항이 있으신 분들은

info@classmethod.kr 로 연락 주시면 빠른 시일 내 담당자가 회신 드릴 수 있도록 하겠습니다 !

--

--