我们能否通过 AWS Cloudformation 动态创建密钥对并将 .PEM 文件复制到 EC2 Linux 实例

Posted

技术标签:

【中文标题】我们能否通过 AWS Cloudformation 动态创建密钥对并将 .PEM 文件复制到 EC2 Linux 实例【英文标题】:Can we dynamically create Keypair through AWS Cloudformation and copy the .PEM file to EC2 Linux instance 【发布时间】:2020-05-16 00:32:27 【问题描述】:

我的要求是创建一个 EC2 实例,该实例将从相同的 Cloudformation 模板动态创建密钥对。截至目前,我正在从 AWS 控制台创建密钥对,并通过 Cloudformation 将其分配给 EC2 实例,方法是从用户。

我查看了 AWS 文档,发现 KeyPair 可以从 AWS 控制台创建。

无论如何可以通过它从 Cloudformation 创建密钥对并将 .PEM 文件复制到实例中。

【问题讨论】:

【参考方案1】:

这是关于私钥管理的。

EC2 密钥对有两个组件。公立和私立。公钥是 AWS 在创建实例时存储并推送到实例的内容。私钥永远不会存储在 AWS。在您使用控制台或通过 CLI 创建密钥对的那一刻 - 您有一个也是唯一的机会将其存储在您的机器上。

Cloud Formation 无法将私钥存储在您的机器上作为堆栈初始化的一部分。

您可以在这里考虑两步法:

1) 创建密钥或从您的计算机导入密钥。无论哪种方式,只有您可以访问私钥部分。

aws ec2 import-key-pair
or
aws ec2 create-key-pair

2) 在 cloudformation 中使用这个新创建的密钥。

  SshKeyParameter:
    Description: SSH Keypair to login to the instance
    Type: AWS::EC2::KeyPair::KeyName
...
      KeyName: !Ref SshKeyParameter

【讨论】:

在 AWS 中是否有我可以安全保存 .PEM 文件的地方,并且在从 cloudformation 创建 EC2 实例时,我可以在 EC2 机器中下载该文件。 理论上,您可以使用 ssh-keygen 生成密钥的实例/容器创建嵌套模板,向 AWS EC2 注册该密钥,将私有密钥保存在 AWS Secrets 中并返回密钥名称作为模板输出。但这似乎太麻烦了,而且无论如何都可能违反安全最佳实践。【参考方案2】:

安东的回答是正确的。 但是,也有使用其他工具的替代方法。通常它们允许自动导入公钥。

Ansible:https://docs.ansible.com/ansible/latest/collections/amazon/aws/ec2_key_module.html#ansible-collections-amazon-aws-ec2-key-module

地形:https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair

甚至:https://binx.io/blog/2017/10/25/deploying-private-key-pairs-with-aws-cloudformation/

【讨论】:

【参考方案3】:

按照安东的回答,它的工作正常。编写的启动 cloudformation 模板的 shell 脚本,如果未预设密钥,脚本将创建它并将其上传到 s3 存储桶。

#!/bin/bash
Region=eu-central-1
key=myapp-engine-$Region
Available_key=`aws ec2 describe-key-pairs --key-name $key | grep KeyName | awk -F\" 'print $4'`

if [ "$key" = "$Available_key" ]; then
    echo "Key is available."
else
    echo "Key is not available: Creating new key"
    aws ec2 create-key-pair --key-name $key --region $Region > myapp-engine-$Region.pem
    aws s3 cp myapp-engine-$Region.pem s3://mybucket/myapp-engine-$Region.pem
fi

##### create stack  #########

/usr/local/bin/aws cloudformation deploy  --stack-name myapp-engine --template-file ./lc.yml --parameter-overrides file://./config.json  --region $Region

以下是 CloudFormation 启动配置堆栈示例,您可以在其中传递密钥。

Resources:
  renderEnginelc:
    Type: AWS::AutoScaling::LaunchConfiguration
    Properties:
      ImageId:
        Ref: "AMIID"
      SecurityGroups:
        - Fn::ImportValue:
            !Sub "$SGStackName-myapp"
      InstanceType:
        Ref: InstanceType
      LaunchConfigurationName : !Join [ "-", [ !Ref Environment, !Ref ApplicationName, lc ] ]
      KeyName: !Join [ "-", [ !Ref KeyName, !Ref AWS::Region ] ]

传递 KeyName 的参数值为“myapp-engine”,它将根据 AWS::Region 考虑一个区域

【讨论】:

以上是关于我们能否通过 AWS Cloudformation 动态创建密钥对并将 .PEM 文件复制到 EC2 Linux 实例的主要内容,如果未能解决你的问题,请参考以下文章

Cloudformation 设计器能否为未使用 CFT 启动的资源生成可视化

AWS CloudFormation入门实践

AWS::CloudFormation::Init 它是如何工作的?

通过 CloudFormation 为现有表添加自动缩放到 AWS DynamoDB

AWS Cloudformation - Helper Scripts

AWS Cloudformation - Parameter Store