{SecretsManager}AWS Secrets Managerシークレットのローテーション



https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/rotating-secrets.html

https://blog.serverworks.co.jp/secrets-manager-rotation

https://random-tech-note.jp/rds-rotate-password/

https://docs.aws.amazon.com/ja_jp/secretsmanager/latest/userguide/tutorials_rotation-single.html


-- 1. コマンド等のインストール

-- 1.1 aws cli version 2 インストール

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
aws --version

-- 1.2 jqインストール
sudo yum -y install jq


-- 1.3 MySQL 8クライアントのインストール


sudo yum -y remove mariadb-libs

sudo yum -y localinstall https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm

sudo yum-config-manager --disable mysql57-community
sudo yum-config-manager --enable mysql80-community

sudo yum info mysql-community-client

sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
sudo yum -y install mysql-community-client

mysql --version

-- 1.4 gitインストール

sudo yum -y install git

 

-- 2. RDSインスタンス作成

aws rds create-db-instance \
--db-instance-identifier mysql01 \
--allocated-storage 20 \
--db-instance-class db.t3.micro \
--engine mysql \
--master-username root \
--master-user-password 'password' \
--no-multi-az \
--engine-version 8.0.28 \
--storage-type gp2 \
--no-publicly-accessible \
--no-enable-performance-insights \
--no-auto-minor-version-upgrade

aws rds describe-db-instances

 

-- 3. シークレット作成

vim secret02.json

{
  "username": "root",
  "password": "password",
  "engine": "mysql",
  "host": "mysql01.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com",
  "port": "3306",
  "dbInstanceIdentifier": "mysql01"
}


aws secretsmanager list-secrets

aws secretsmanager create-secret \
--name secret02 \
--secret-string file://secret02.json

aws secretsmanager describe-secret \
--secret-id secret02

 

aws secretsmanager get-secret-value \
--secret-id secret02

 


-- 4. 接続確認(ローテーション実行前)

aws secretsmanager get-secret-value \
--secret-id secret02 | jq .SecretString

secretstring=$(aws secretsmanager get-secret-value --secret-id secret02 | jq -r .SecretString)

username=$(echo $secretstring | jq -r .username)
password=$(echo $secretstring | jq -r .password)
host=$(echo $secretstring | jq -r .host)
port=$(echo $secretstring | jq -r .port)

echo $secretstring
echo $username
echo $password
echo $host
echo $port


mysql -h $host -P $port -u $username -p$password

 

-- 5. シークレットのローテーションを有効化


-- 5.1 IAMポリシー作成

vim policy01.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "ec2:CreateNetworkInterface",
                "ec2:DescribeNetworkInterfaces",
                "ec2:DeleteNetworkInterface",
                "ec2:AssignPrivateIpAddresses",
                "ec2:UnassignPrivateIpAddresses",
                "ec2:DetachNetworkInterface"
            ],
            "Resource": "*"
        },
        {
            "Condition": {
                "StringEquals": {
                    "secretsmanager:resource/AllowRotationLambdaArn": "arn:aws:lambda:ap-northeast-1:999999999999:function:func01"
                }
            },
            "Action": [
                "secretsmanager:DescribeSecret",
                "secretsmanager:GetSecretValue",
                "secretsmanager:PutSecretValue",
                "secretsmanager:UpdateSecretVersionStage"
            ],
            "Resource": "arn:aws:secretsmanager:ap-northeast-1:999999999999:secret:*",
            "Effect": "Allow"
        },
        {
            "Action": [
                "secretsmanager:GetRandomPassword"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

 


aws iam create-policy \
--policy-name policy01 \
--policy-document file://policy01.json


-- 5.2 IAMロール作成
vim role01.json

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

aws iam create-role \
--role-name role01 \
--assume-role-policy-document file://role01.json


-- 5.3 ポリシーをロールにアタッチ
aws iam attach-role-policy \
--policy-arn arn:aws:iam::999999999999:policy/policy01 \
--role-name role01

 

-- 5.4 Lambda関数作成


git clone https://github.com/aws-samples/aws-secrets-manager-rotation-lambdas.git

cp /home/ec2-user/aws-secrets-manager-rotation-lambdas/SecretsManagerRDSMySQLRotationSingleUser/lambda_function.py .


mkdir package
pip3 install pymysql asn1crypto cryptography --target ./package
ll package


chmod 755 lambda_function.py
chmod -R 755 package

cd package
zip -r ../test.zip .
cd ..
zip -g test.zip lambda_function.py

 

vim env.json

{
    "Variables": {
        "EXCLUDE_CHARACTERS": "/@\"'\\",
        "SECRETS_MANAGER_ENDPOINT": "https://secretsmanager.ap-northeast-1.amazonaws.com"
    }
}


aws lambda create-function \
--function-name func01  \
--zip-file fileb://test.zip \
--role arn:aws:iam::999999999999:role/role01 \
--handler lambda_function.lambda_handler \
--runtime python3.7 \
--timeout 30 \
--memory-size 128 \
--vpc-config SubnetIds=subnet-11111111111111111,subnet-22222222222222222,subnet-33333333333333333,SecurityGroupIds=sg-44444444444444444 \
--environment file://env.json \
--tracing-config '{
            "Mode": "PassThrough"
        }'

 


aws lambda list-functions | grep func01

aws lambda get-function --function-name func01


-- 5.5 Lambda関数に権限を追加する


aws lambda add-permission \
--function-name func01 \
--statement-id SecretsManagerAccess \
--action lambda:InvokeFunction \
--principal secretsmanager.amazonaws.com

 

aws lambda get-policy \
--function-name func01 | jq -r .Policy  | jq .

 

 

-- 5.6 Secrets Manager サービスのVPCエンドポイント作成

aws ec2 create-vpc-endpoint \
--vpc-endpoint-type Interface \
--vpc-id vpc-55555555555555555 \
--service-name com.amazonaws.ap-northeast-1.secretsmanager \
--subnet-ids "subnet-11111111111111111" "subnet-22222222222222222" "subnet-33333333333333333" \
--security-group-ids "sg-44444444444444444" \
--private-dns-enabled


aws ec2 describe-vpc-endpoints

 

-- 5.7 シークレットの自動ローテーションを有効化

aws secretsmanager rotate-secret \
--secret-id secret02 \
--rotation-lambda-arn arn:aws:lambda:ap-northeast-1:999999999999:function:func01 \
--rotation-rules "{\"ScheduleExpression\": \"cron(0 1 1 * ? *)\", \"Duration\": \"1h\"}" \
--rotate-immediately

 

CloudwatchLogを確認

 


-- 6. 接続確認(ローテーション実行後)

aws secretsmanager get-secret-value \
--secret-id secret02 | jq .SecretString

secretstring=$(aws secretsmanager get-secret-value --secret-id secret02 | jq -r .SecretString)

username=$(echo $secretstring | jq -r .username)
password=$(echo $secretstring | jq -r .password)
host=$(echo $secretstring | jq -r .host)
port=$(echo $secretstring | jq -r .port)

echo $secretstring
echo $username
echo $password
echo $host
echo $port


mysql -h $host -P $port -u $username -p$password

 


-- 7. クリーンアップ

-- VPCエンドポイントの削除

aws ec2 describe-vpc-endpoints

aws ec2 delete-vpc-endpoints \
--vpc-endpoint-ids vpce-66666666666666666

 

 

-- Lambda関数の削除
aws lambda list-functions | grep func01

aws lambda delete-function --function-name func01

 

-- IAMロールの削除
aws iam list-roles | grep role01

aws iam detach-role-policy \
--role-name role01 \
--policy-arn arn:aws:iam::999999999999:policy/policy01

aws iam delete-role --role-name role01


-- IAMポリシーの削除
aws iam list-policies | grep policy01

aws iam delete-policy \
--policy-arn arn:aws:iam::999999999999:policy/policy01

 

-- シークレット削除
aws secretsmanager list-secrets

aws secretsmanager delete-secret \
--secret-id secret02 \
--force-delete-without-recovery

 

--  RDS データベースインスタンス削除
aws rds describe-db-instances

aws rds delete-db-instance \
--db-instance-identifier mysql01 \
--skip-final-snapshot