5

My requirement is to create an EC2 instance which will have the Keypair created dynamically from the same Cloudformation template.As of now,I am creating the KeyPair from AWS console and assigning it to EC2 instance through Cloudformation by taking the input from the user.

I have checked AWS document and found that the KeyPair can be create from AWS console.

Is there anyway through which Keypair can be created from Cloudformation and copy the .PEM file in the instance.

Amit Chandra
  • 61
  • 1
  • 1
  • 3

4 Answers4

8

It's about private key management.

EC2 Keypair has two components. Public and private. The public key is what AWS stores and pushes to the instance on instance creation. The private key is never stored at AWS. The moment you create keypair either with the console or via CLI - you have the one and only chance to store it on your machine.

Cloud formation has no way of storing the private key on your machine as a part of the stack initialization.

You might consider two-step approach here:

1) Either create the key or import one from your machine. In either way you and only you would have access to the Private key part.

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

2) Use this newly created key in cloudformation.

  SshKeyParameter:
    Description: SSH Keypair to login to the instance
    Type: AWS::EC2::KeyPair::KeyName
...
      KeyName: !Ref SshKeyParameter
Anton
  • 3,587
  • 2
  • 12
  • 27
  • Is there anyway in AWS where I can keep the .PEM file safely and while creating the EC2 instance from cloudformation,I can download the file in EC2 machine. – Amit Chandra Jan 31 '20 at 05:18
  • 1
    In theory, you can create the nested template with the instance/container that would generate the key using ssh-keygen, register that key with AWS EC2, save the private key in AWS Secrets and return the key name as the template output. But it seems like too big of a hassle and likely against the security best practices anyways. – Anton Jan 31 '20 at 15:16
1

followed the Anton's answer and its works fine. written shell script which is launching a cloudformation template and if key is not preset ,script willl create it and will upload it to the s3 bucket.

#!/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

Below is an example of a CloudFormation launch configuration stack where you can pass the key.

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 ] ]

Passing a paramter value of KeyName is "myapp-engine" and it will consider a region according to AWS::Region

mahendra rathod
  • 1,438
  • 2
  • 15
  • 23
0

Anton's answer is correct. However, there are alternatives using other tools. Usually they allow to automate the public key import.

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

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

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

Federico
  • 1,636
  • 2
  • 22
  • 24
0

According to the documentation, it is (now) possible to create a key pair with cloudformation:

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-keypair.html

To create a new key pair, omit the PublicKeyMaterial property.

When you create a new key pair, the private key is saved to AWS Systems Manager Parameter Store, using a parameter with the following name: /ec2/keypair/{key_pair_id}. For more information about retrieving private key, and the required permissions, see Create a key pair using AWS CloudFormation in the Amazon EC2 User Guide.

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/create-key-pairs.html#create-key-pair-cloudformation

neuquen
  • 3,991
  • 15
  • 58
  • 78