Reputation: 12407
I would like to create a CloudFormation stack with the CLI command provided below:
$ aws cloudformation create-stack --region us-east-1 --stack-name c3-app --template-body file://starter/c3-app.yml --parameters ParameterKey=KeyPair,ParameterValue=chaklader.pem --capabilities CAPABILITY_IAM
My pem key is in the same folder from where I run this command:
This doesn't create the stack and I get the error message from the events log:
AWS Cloudformation The key pair 'chaklader.pem' does not exist (Service: AmazonEC2; Status Code: 400; Error Code: InvalidKeyPair.
My CloudFormation template is provided below:
Description: This template deploys ec2 instances for the project starter
Parameters:
AmiIdRecipeWebServiceInstance:
Type: String
Default: "ami-0964e67a489e13cdb"
AmiIdAttackInstance:
Type: String
Default: "ami-01fcf79ce78f46764"
KeyPair:
Type: String
Description: "Name of an existing KeyPair you will use to access the EC2 instances in this exercise. Be sure you have access to the private key file corresponding to this keypair."
Resources:
InstanceRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: InstanceRolePolicy-C3
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: 's3:*'
Resource: '*'
InstanceProfileRole:
Type: AWS::IAM::InstanceProfile
Properties:
Path: /
Roles:
- !Ref InstanceRole
WebAppSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: WebAppSG
GroupDescription: "Security group for this application server"
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
SecurityGroupIngress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 5000
ToPort: 5000
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
VpcId: !ImportValue VpcId
RecipeWebServiceInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AmiIdRecipeWebServiceInstance
InstanceType: t3.micro
KeyName: !Ref KeyPair
SecurityGroupIds:
- !GetAtt WebAppSG.GroupId
SubnetId: !ImportValue PublicSubnetTrusted
IamInstanceProfile: !Ref InstanceProfileRole
Tags:
- Key: "Name"
Value: "Web Service Instance - C3"
UserData:
Fn::Base64:
Fn::Sub:
- |
#!/bin/bash
echo "Environment=S3_FREE_RECIPES="${S3FreeRecipies} | sudo tee -a /lib/systemd/system/flask.service
echo "Environment=S3_SECRET_RECIPES="${S3SecretRecipies} | sudo tee -a /lib/systemd/system/flask.service
systemctl daemon-reload
sleep 30
service flask restart
- S3FreeRecipies: !ImportValue BucketNameRecipesFree
S3SecretRecipies: !ImportValue BucketNameRecipesSecret
# Add code for Exercise 3
AppLoadBalancerSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: AppLoadBalancerSG
GroupDescription: "Security group for this application server"
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
VpcId: !ImportValue VpcId
AppEIP:
Type: AWS::EC2::EIP
Properties:
InstanceId: !Ref RecipeWebServiceInstance
AppLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: c1-web-service-alb
SecurityGroups:
- !GetAtt AppLoadBalancerSG.GroupId
Subnets:
- !ImportValue PublicSubnetTrusted
- !ImportValue PublicSubnetUnTrusted
AppLoadBalancerListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref AppTargetGroup
LoadBalancerArn: !Ref AppLoadBalancer
Port: 80
Protocol: HTTP
AppTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
HealthCheckEnabled: true
HealthCheckIntervalSeconds: 10
HealthCheckPath: /health
Name: AppTargetGroup
Port: 5000
VpcId: !ImportValue VpcId
Protocol: HTTP
Targets:
- Id: !Ref RecipeWebServiceInstance
AttackInstanceSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: AttackInstanceSG
GroupDescription: "Security group for the attack instance"
SecurityGroupEgress:
- IpProtocol: -1
CidrIp: 0.0.0.0/0
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
VpcId: !ImportValue VpcId
AttackInstance:
Type: AWS::EC2::Instance
Properties:
ImageId: !Ref AmiIdAttackInstance
InstanceType: t3.micro
KeyName: !Ref KeyPair
IamInstanceProfile: !Ref InstanceProfileRole
SecurityGroupIds:
- !GetAtt AttackInstanceSG.GroupId
SubnetId: !ImportValue PublicSubnetUnTrusted
Tags:
- Key: "Name"
Value: "Attack Instance - C3"
Outputs:
AttackInstanceIP:
Value: !GetAtt AttackInstance.PublicDnsName
ApplicationInstanceIP:
Value: !GetAtt RecipeWebServiceInstance.PublicDnsName
ApplicationURL:
Value: !GetAtt AppLoadBalancer.DNSName
I created a new keypair with the command provided as suggested in answer:
aws ec2 create-key-pair --key-name arefe --query "KeyMaterial" --output text > arefe.pem
chmod 400 arefe.pem
Then, run the command again:
aws cloudformation create-stack --region us-east-1 --stack-name c3-app --template-body file://starter/c3-app.yml --parameters ParameterKey=KeyPair,ParameterValue=arefe.pem --capabilities CAPABILITY_IAM
I still receive the same error:
The key pair 'arefe.pem' does not exist (Service: AmazonEC2; Status Code: 400; Error Code: InvalidKeyPair.NotFound; Request ID: aceed5ea-7841-4056-8738-e02a1f921b90; Proxy: null)
What's the issue here?
Upvotes: 0
Views: 679
Reputation: 238189
CloudFormation (CFN) is not going to take your chaklader.pem
and create a pair key in AWS. You have to do it before hand yourself. And you can't use CFN for that as it is not supported, unless you will program such a logic yourself using custom resource.
The easiest way is to create or import the key "manually" using AWS Console, SDK or CLI. Then you can reference its name in your template.
Upvotes: 1