无论如何,我们可以将dynamic references传递到Secret Manager到AWS Launch Config用户数据吗?
这是我尝试过的代码段:
"SampleLaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"ImageId": {
"Fn::FindInMap": [
"AWSRegionArch2AMI",
{
"Ref": "AWS::Region"
},
"AMI"
]
},
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash -xe\n",
"yum update -y\n",
"useradd -p <<pwd>>{{resolve:secretsmanager:Credentials:SecretString:userName}}\n",
"\n"
]
]
}
}
}
}
在获取useradd时似乎出错:无效的用户名'{{resolve:secretsmanager:Credentials:SecretString:userName}}'
如何将Secret Manager机密值传递给cloudformation用户数据?
答案 0 :(得分:3)
似乎{{resolve:...}}
动态引用仅在模板中的某些上下文中扩展。
AWS文档中没有关于可以使用这些引用的确切位置的确切信息。关于{{resolve:secretsmanager:...}}
的当前措辞如下:
“ secretsmanager动态引用可以在所有资源属性中使用”
但是,这与您的示例相矛盾,并且我还观察到动态引用未能在CloudFormation :: Init数据内部解析。
我正在就此问题与AWS展开积极的支持案例,他们同意没有充分记录动态引用的行为。当我了解更多信息时,我将更新此答案。
答案 1 :(得分:2)
我不确定为什么无法为您正确展开此内容。但是,您可能不希望CFN在用户数据中扩展秘密,因为密码将嵌入在EC2控制台中可见的base64编码的用户数据脚本中。
相反,您应该利用以下事实:您有一个脚本在主机上执行,并在脚本执行时调用秘密管理器(警告未经测试):
"SampleLaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"ImageId": {
"Fn::FindInMap": [
"AWSRegionArch2AMI",
{
"Ref": "AWS::Region"
},
"AMI"
]
},
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash -xe\n",
"yum update -y\n",
"yum install -y jq\n",
!Sub "useradd -p `aws --region ${AWS::Region} secretsmanager get-secret-value --secret-id Credentials --query SecretString --output text | jq -r .passwordKey` `aws --region ${AWS::Region} secretsmanager get-secret-value --secret-id Credentials --query SecretString --output text | jq -r .userName`\n",
"\n"
]
]
}
}
}
}
这并不理想,因为它在命令行上扩展了密码。首先将密码放在文件中,然后从那里读取密码,然后将其切碎,可以使其更加安全。
答案 2 :(得分:1)
我可以确认@JoeB的“警告未经测试”的答案有效,但需要注意的是,有关机器必须具有读取机密的权限。您将需要类似
的内容 MyInstancePolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: MyPolicy
PolicyDocument:
Version: 2012-10-17
Statement:
-
Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: !Join
- ''
- - !Sub "arn:aws:secretsmanager:${AWS::Region}:"
- !Sub "${AWS::AccountId}:secret:Credentials-??????"
请注意以下几点:
与S3存储桶不同,您无法执行arn:aws:secretsmanager:::secret...
。如果您不想显式声明区域和帐户,则需要使用通配符。埋在Using Identity-based Policies (IAM Policies) for Secrets Manager
如果您不关心拥有秘密的地区或帐户, 您必须为通配符指定一个通配符*(而不是一个空字段) ARN的区域和帐户ID号字段。
也许不那么重要,并且不太可能导致意外故障,但是仍然值得注意:
使用'??????'作为通配符来匹配6个随机字符 由Secrets Manager分配,可以避免出现以下问题: 请改用'*'通配符。如果使用语法 “ another_secret_name- *”,它不仅与 6个随机字符,但也可以匹配 “ another_secret_name-a1b2c3”。使用 '??????'句法 使您能够安全地将权限授予尚未存在的机密 存在。
答案 3 :(得分:1)
@JoeB回答中的变体形式:
Resources:
SampleLaunchConfig:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
ImageId: !FindInMap [ AWSRegionArch2AMI, !Ref: 'AWS::Region', AMI ]
UserData:
Fn::Base64: !Sub |
#!/bin/bash -xe
exec > >(tee /var/log/user-data.log | logger -t user-data) 2>&1
yum update -y
yum install -y jq
username=$(aws secretsmanager get-secret-value --secret-id Credentials \
--query SecretString \
--region ${AWS::Region} --output text | jq -r .userName)
password=$(aws secretsmanager get-secret-value --secret-id Credentials \
--query SecretString \
--region ${AWS::Region} --output text | jq -r .passwordKey)
useradd -p "$password" $username
如今,JSON中的UserData让人很难看。
我还添加了一种将UserData逻辑拆分到其自己的日志文件中的技术,否则它会进入cloud-init.log,这也很难读取。
答案 4 :(得分:1)
执行此操作的正确方法是致电Secret Manager以获取您的数据,这是我成功进行的操作:
SftpCredsUserPasswordSecret:
Type: 'AWS::SecretsManager::Secret'
Properties:
Name: 'sftp-creds-user-password-secret'
Description: DB Credentials
GenerateSecretString:
SecretStringTemplate: '{"username":"sftpuser"}'
GenerateStringKey: "password"
PasswordLength: 30
ExcludePunctuation: true
Ec2SftpRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument: # Tells that Ec2 can assume this role
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Principal:
Service:
- ec2.amazonaws.com
Policies: # Tells that you can call for the secret value
- PolicyName: "root"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action: "secretsmanager:GetSecretValue"
Resource: !Ref SftpCredsUserPasswordSecret
RoleName: 'role-ec2-sftp'
Ec2SftpIamInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
InstanceProfileName: 'instance-profile-ec2-sftp'
Roles:
- !Ref Ec2SftpRole
Ec2Sftp:
Type: AWS::EC2::Instance
Properties:
ImageId: "ami-06ce3edf0cff21f07"
InstanceType: t2.micro
SecurityGroupIds:
- !ImportValue SgBridgeId
- !ImportValue SgSftpId
SubnetId: !ImportValue PublicSubnetAZbId
KeyName: !Ref KeyName
UserData:
Fn::Base64: !Sub
- |
#!/bin/bash
# Get Variables
secret=`aws --region ${AWS::Region} secretsmanager get-secret-value --secret-id ${secretRef} --query SecretString --output text`
sftpuser=`echo "$secret" | sed -n 's/.*"username":["]*\([^(",})]*\)[",}].*/\1/p'`
sftppassword=`echo "$secret" | sed -n 's/.*"password":["]*\([^(",})]*\)[",}].*/\1/p'`
# Create Sftp User
adduser $sftpuser
echo "$sftpuser:$sftppassword" | chpasswd
# Configure sftp connection
echo "" >> /etc/ssh/sshd_config
echo "Match User $sftpuser" >> /etc/ssh/sshd_config
echo " PasswordAuthentication yes" >> /etc/ssh/sshd_config
echo " ForceCommand /usr/libexec/openssh/sftp-server" >> /etc/ssh/sshd_config
# Restart the service
systemctl restart sshd
-
secretRef: !Ref SftpCredsUserPasswordSecret
IamInstanceProfile: !Ref Ec2SftpIamInstanceProfile
Tags:
- Key: Name
Value: 'ec2-sftp'
答案 5 :(得分:0)
AWS CloudFormation 增强了 CloudFormation 模板中 AWS Systems Manager Parameter Store 参数的现有动态引用。您现在可以在 CloudFormation 模板中引用最新的 Systems Manager 参数值,而无需指定参数版本。
查看更多