Know How Guide and Hands on Guide for AWS
Official guide for Automating secret creation in AWS CloudFormation
The secret has a resource-based policy attached that specifies access to the secret. The template also creates a Lambda rotation function and configures the secret to automatically rotate every 30 days.
EnableRotation
as true
.EnableRotation
as true
.TestEC2SecurityGroupId
is Security group of EC2 which connect to RDS MySQLTestSecretArn
is the existed secret in your account or other accountTestSubnet01
, TestSubnet02
and TestVpcId
are IDs hosted new created RDS MySQLConnect the RDS with credentials stored in the Secrets Manager as the master user and password.
The RDS endpoint and port can get from CloudFormation stack Outputs
In my demo, I use the existed secret named quickstart/MyCustomTypeSecret
# Check the secret
aws secretsmanager describe-secret --secret-id quickstart/MyCustomTypeSecret --region cn-north-1
# Get the value of master user and password
masterUser=$(aws secretsmanager get-secret-value --secret-id quickstart/MyCustomTypeSecret --version-stage AWSCURRENT --output json --region cn-north-1 | jq -r .SecretString | jq -r .username )
echo $masterUser
masterPassword=$(aws secretsmanager get-secret-value --secret-id quickstart/MyCustomTypeSecret --version-stage AWSCURRENT --output json --region cn-north-1 | jq -r .SecretString | jq -r .password )
echo $masterPassword
# Get the RDS MySQL endpoint
dbEndPoint=$(aws cloudformation describe-stacks --region cn-north-1 --stack-name Screte-Mgr-RDS --query 'Stacks[0].Outputs[?OutputKey==`dbEndPoint`].OutputValue' --output json | jq -r '.[0]')
# Connect the RDS MySQL
mysql -h $dbEndPoint -u $masterUser -p
Step 1: Create and attach a resource policy for Security_Account
Security_Account is the owner of Secrets and policy allow
{
"Version" : "2012-10-17",
"Statement" : [ {
"Effect" : "Allow",
"Principal" : {
"AWS" : ["arn:aws-cn:iam::Dev_Account:role/ec2-secrets-role","arn:aws-cn:iam::Dev_Account:role/cloudformation-role"]
},
"Action" : ["secretsmanager:GetSecretValue","secretsmanager:DescribeSecret"],
"Resource" : "*"
}
]
}
Step 2: Update the KMS key policy in your Security_Account account
Allow Dev_Account role to use the KMS key to decrypt secrets of Security_Account when retrieve the them
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws-cn:iam::Security_Account:role/Admin",
"arn:aws-cn:iam::Dev_Account:role/ec2-secrets-role",
"arn:aws-cn:iam::Dev_Account:role/cloudformation-role"
]
},
"Action": [
"kms:Decrypt",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "arn:aws-cn:kms:cn-north-1:Security_Account:key/SECETES_CMK"
}
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue","secretsmanager::DescribeSecret"],
"Resource": " arn:aws-cn:secretsmanager:cn-north-1:Security_Account:secret:SecurityAcount/SharedSecrets/RDSMySQL"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:DescribeKey"
],
"Resource": "arn:aws-cn:kms:cn-north-1:Security_Account:key/SECETES_CMK"
}
]
}
Step 4: Test access to the SECURITY_SECRET from the Dev_Account account
aws sts get-caller-identity --region cn-north-1
aws secretsmanager describe-secret --secret-id "arn:aws-cn:secretsmanager:cn-north-1:Security_Account:secret:SecurityAcount/SharedSecrets/RDSMySQL" --region cn-north-1
aws secretsmanager get-secret-value --secret-id "arn:aws-cn:secretsmanager:cn-north-1:Security_Account:secret:SecurityAcount/SharedSecrets/RDSMySQL" --version-stage AWSCURRENT --region cn-north-1
EnableRotation
as true
.TestEC2SecurityGroupId
is Security group of EC2 which connect to RDS MySQLTestSecretArn
is the existed secret in Security_Account SecurityAcount/SharedSecrets/RDSMySQL
TestSubnet01
, TestSubnet02
and TestVpcId
are IDs hosted new created RDS MySQLcloudformation-role
to create the CloudFormation have below policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue","secretsmanager::DescribeSecret"],
"Resource": " arn:aws-cn:secretsmanager:cn-north-1:Security_Account:secret:SecurityAcount/SharedSecrets/RDSMySQL"
},
{
"Effect": "Allow",
"Action": [
"kms:Decrypt",
"kms:DescribeKey"
],
"Resource": "arn:aws-cn:kms:cn-north-1:Security_Account:key/SECETES_CMK"
}
]
}
Connect the RDS with credentials stored in the Secrets Manager as the master user and password.
The RDS endpoint and port can get from CloudFormation stack Outputs
In my demo, I use the existed secret named SecurityAcount/SharedSecrets/RDSMySQL
sudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
sudo yum install -y mysql-community-client
sudo yum install -y jq
# Get the value of master user and password
masterUser=$(aws secretsmanager get-secret-value --secret-id "arn:aws-cn:secretsmanager:cn-north-1:SecurityAcount:secret:SecurityAcount/SharedSecrets/RDSMySQL" --version-stage AWSCURRENT --output json --region cn-north-1 | jq -r .SecretString | jq -r .username )
echo $masterUser
masterPassword=$(aws secretsmanager get-secret-value --secret-id "arn:aws-cn:secretsmanager:cn-north-1:SecurityAcount:secret:SecurityAcount/SharedSecrets/RDSMySQL" --version-stage AWSCURRENT --output json --region cn-north-1 | jq -r .SecretString | jq -r .password )
echo $masterPassword
# Get the RDS MySQL endpoint
dbEndPoint=$(aws cloudformation describe-stacks --region cn-north-1 --stack-name Screte-Mgr-RDS --query 'Stacks[0].Outputs[?OutputKey==`dbEndPoint`].OutputValue' --output json | jq -r '.[0]')
echo $dbEndPoint
# Connect the RDS MySQL
mysql -h $dbEndPoint -u $masterUser -p
aws cloudformation delete-stack --stack-name Screte-Mgr-RDS --region cn-north-1
Delete your Testing EC2