Parameters: [KeyPair] must have values - amazon-web-services

I am trying to mirror my EC2 instance using cloudformation. Currently, I've been able to create the following JSON using troposphere and I come across the error 'Parameters: [KeyPair] must have values'. I am not sure what this 'values' has to be?
I understand the error but not sure what's the solution.
{
"Outputs": {
"InstanceAccess": {
"Description": "",
"Value": {
"Fn::Join": [
"",
[
"ssh -i ",
{
"Ref": "KeyPair"
},
" ubuntu#",
{
"Fn::GetAtt": [
"MyInstance",
"PublicDnsName"
]
}
]
]
}
}
},
"Parameters": {
"KeyPair": {
"Description": "jj",
"Type": "AWS::EC2::KeyPair::launch"
}
},
"Resources": {
"MyInstance": {
"Properties": {
"ImageId": "< my image id goes here>",
"InstanceType": "t1.micro",
"KeyName": {
"Ref": "KeyPair"
},
"SecurityGroups": [
{
"Ref": "SecurityGroup"
}
]
},
"Type": "AWS::EC2::Instance"
},
"SecurityGroup": {
"Properties": {
"GroupDescription": "Allow access to MyInstance",
"SecurityGroupIngress": [
{
"CidrIp": "0.0.0.0/0",
"FromPort": "22",
"IpProtocol": "tcp",
"ToPort": "22"
},
{
"CidrIp": "0.0.0.0/0",
"FromPort": "80",
"IpProtocol": "tcp",
"ToPort": "80"
},
{
"CidrIp": "0.0.0.0/0",
"FromPort": "8080",
"IpProtocol": "tcp",
"ToPort": "8080"
},
{
"CidrIp": "0.0.0.0/0",
"FromPort": "443",
"IpProtocol": "tcp",
"ToPort": "443"
}
]
},
"Type": "AWS::EC2::SecurityGroup"
}
}
}

Your KeyPair parameter should have a valid type. According to the Parameters section of the CloudFormation User Guide, the type for a KeyPair parameter is AWS::EC2::KeyPair::KeyName. So it should look like this:
"KeyPair": {
"Description": "The name of the keypair to use for SSH access",
"Type": "AWS::EC2::KeyPair::KeyName"
}
Also, if you declare a key pair name as a parameter in your template, you'll have to pass an existing key pair name as an argument when you create a stack using that template.

To expand on the accepted answer, you can add a default value for the parameter. This would have also resolved the error you were seeing. If KeyPair has a static value, you may prefer a default over passing an argument. You can still override the default by passing an argument.
"KeyPair": {
"Description": "The name of the keypair to use for SSH access",
"Type": "AWS::EC2::KeyPair::KeyName",
"Default": "launch"
}

Related

AWS Cloud formation - create EC2 instance with security group name

I am trying to create a cloud formation template to create EC2 instance. I would like to use Security Group Name instead of Security Group Id. When I use that I am getting error "Encountered unsupported property SecurityGroup". How can I use Security Group Name while creating EC2 Instance through Cloud Formation
"Resources":
{
"EC2Instance":
{
"Type" : "AWS::EC2::Instance",
"Properties":
{
"InstanceType":
{
"Ref": "InstanceType"
},
"SecurityGroup":
[
{
"Ref" : "InstanceSecurityGroup"
}
],
"KeyName":
{
"Ref" : "AWS::Region"
},
"ImageId":
{
"Ref": "AMI"
}
}
},
"InstanceSecurityGroup":
{
"Type":"AWS::EC2::SecurityGroup",
"Properties":
{
"GroupDescription": "Enable SSH access via port 22",
"GroupName":
{
"Fn::FindInMap":
[
"EnvironmentConfig",
{
"Ref": "Environment"
},
"SGGroupName"
]
},
"SecurityGroupIngress":
[
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"CidrIp":"10.252.0.0/16"
},
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"CidrIp":"10.251.0.0/16"
}
],
"VpcId":
{
"Fn::FindInMap":
[
"EnvironmentConfig",
{
"Ref":"Environment"
},
"VPC"
]
}
}
}
It should be SecurityGroups instead of SecurityGroup, i.e.
"SecurityGroups" : [{ "Ref" : "InstanceSecurityGroup" }]
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-ec2.html

Security Group and Subnet Belongs to different networks

I am creating a basic AWS CloudFormation Template with one VPC, 3 Security Group and 5 EC2 Instances my security group looks something like this -
{
"WebApplicationServerSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"VpcId": {
"Ref": "DevVpc"
},
"GroupDescription": "Enable HTTP, HTTPS and SSH access",
"Tags": [
{
"Key": "Name",
"Value": "WebApplicationServer Service Group"
}
],
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
]
},
"Metadata": {
"AWS::CloudFormation::Designer": {
"id": "a7977f00-48d6-488f-9e23-9bcd0785d399"
}
}
}
}
And the VPC is something like below -
{
"DevVpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "172.31.0.0/16",
"EnableDnsSupport": "false",
"EnableDnsHostnames": "false",
"InstanceTenancy": "dedicated",
"Tags": [
{
"Key": "Name",
"Value": "DevStackVpc"
}
]
}
}
}
I am getting error while stack creation with the template -
Security group sg-31f91b5a and subnet subnet-ea0aa3a7 belong to
different networks.
11:13:01 UTC+0550 CREATE_FAILED AWS::EC2::Instance WebApplicationServer Security group sg-5147a53a and subnet subnet-ea0aa3a7 belong to different networks.
And here is a gist for complete template, any help would really be appreciated.
If anyone using Terraform got here, I had a similar error message and what ended up happening was the following:
variable "name" {}
locals {
vpc_id = "..."
subnet_id = "..."
}
resource "aws_instance" "web" {
ami = "ami-09def150731bdbcc2"
instance_type = "t3.micro"
vpc_security_group_ids = ["${aws_security_group.allow_http.id}"]
user_data = <<-EOF
#!/bin/bash
sudo amazon-linux-extras install nginx1.12 -y
sudo nginx
EOF
tags {
Name = "${var.name}"
}
}
resource "aws_security_group" "allow_http" {
description = "Allow inbound HTTP traffic for ${var.name} instance"
vpc_id = "${local.vpc_id}"
ingress {
from_port = 80
to_port = 80
protocol = "TCP"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
The subnet I was deploying into didn't have auto assign public IPs enabled. As such, I updated the aws_instance to include the subnet_id and associate_public_ip_address:
resource "aws_instance" "web" {
ami = "ami-09def150731bdbcc2"
instance_type = "t3.micro"
subnet_id = "${local.subnet_id}"
vpc_security_group_ids = ["${aws_security_group.allow_http.id}"]
associate_public_ip_address = true
user_data = <<-EOF
#!/bin/bash
sudo amazon-linux-extras install nginx1.12 -y
sudo nginx
EOF
tags {
Name = "${var.name}"
}
}
After which, everything worked.
I got the above problem resolved by the pointers provided in comments, The relation between subnet VPC, Security-Groups and EC2 instance are as below -
1st thing which gets and should be created is VPC
2nd is the Subnet here you mention the VpcId you created earlier
3rd You create security groups here you mention the VpcId you created earlier as well.
4th There is a property NetworkInterfaces where you provide SubnetId and GroupSet which is an array of security group ids and this is where you define the relation between the security group, vpc and subnet and this is what solved the problem.
Below is the sample template which actually worked -
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"DevServerKeyPair": {
"Description": "Name of an existing EC2 KeyPair to enable SSH access to the instance",
"Type": "AWS::EC2::KeyPair::KeyName",
"ConstraintDescription": "Must be the name of an existing EC2 KeyPair."
}
},
"Resources": {
"DevVpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "172.31.0.0/16",
"EnableDnsSupport": "false",
"EnableDnsHostnames": "false",
"InstanceTenancy": "dedicated",
"Tags": [
{
"Key": "Name",
"Value": "DevStackVpc"
}
]
}
},
"DevSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "DevVpc"
},
"CidrBlock": "172.31.0.0/16",
"AvailabilityZone": {
"Fn::Select": [
0,
{
"Fn::GetAZs": ""
}
]
}
}
},
"WebApplicationServerSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"VpcId": {
"Ref": "DevVpc"
},
"GroupDescription": "Enable HTTP, HTTPS and SSH access",
"Tags": [
{
"Key": "Name",
"Value": "WebApplicationServer Service Group"
}
],
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"WebApplicationServer": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-f3e5aa9c",
"InstanceType": "t2.micro",
"Tags": [
{
"Key": "Name",
"Value": "WebApplicationServer"
}
],
"KeyName": {
"Ref": "DevServerKeyPair"
},
"NetworkInterfaces": [
{
"SubnetId": {"Ref": "DevSubnet"},
"AssociatePublicIpAddress": "true",
"DeviceIndex": "0",
"GroupSet": [{ "Ref" : "WebApplicationServerSG" }]
}
]
}
}
}
}
Hope it helps someone looking into similar problem.
The problem with the security group you trying to use! When you create one with a template it used the default VPC.
On the CLoudFormation template where you create a security group, you need to identify VpcId that you like to use (NON-Default), it will solve the problem. Or you can manually create a new security group using (NON-Default)VPC, and then run new instances.

AWS Cloud Formation - Requested configuration not supported AWS::EC2::Instance

I am getting below error on one of my cloud formation template -
13:00:10 UTC+0550 CREATE_FAILED AWS::EC2::Instance WebApplicationServer The requested configuration is currently not supported. Please check the documentation for supported configurations.
My CloudFormation template is -
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"DevServerKeyPair": {
"Description": "Name of an existing EC2 KeyPair to enable SSH access to the instance",
"Type": "AWS::EC2::KeyPair::KeyName",
"ConstraintDescription": "Must be the name of an existing EC2 KeyPair."
}
},
"Resources": {
"DevVpc": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "172.31.0.0/16",
"EnableDnsSupport": "false",
"EnableDnsHostnames": "false",
"InstanceTenancy": "dedicated",
"Tags": [
{
"Key": "Name",
"Value": "DevStackVpc"
}
]
}
},
"DevSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "DevVpc"
},
"CidrBlock": "172.31.0.0/16",
"AvailabilityZone": {
"Fn::Select": [
0,
{
"Fn::GetAZs": ""
}
]
}
}
},
"WebApplicationServerSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"VpcId": {
"Ref": "DevVpc"
},
"GroupDescription": "Enable HTTP, HTTPS and SSH access",
"Tags": [
{
"Key": "Name",
"Value": "WebApplicationServer Service Group"
}
],
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupEgress": [
{
"IpProtocol": "tcp",
"FromPort": "443",
"ToPort": "443",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": "0.0.0.0/0"
},
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"WebApplicationServer": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-f3e5aa9c",
"InstanceType": "t2.micro",
"Tags": [
{
"Key": "Name",
"Value": "WebApplicationServer"
}
],
"KeyName": {
"Ref": "DevServerKeyPair"
},
"NetworkInterfaces": [
{
"SubnetId": {"Ref": "DevSubnet"},
"AssociatePublicIpAddress": "true",
"DeviceIndex": "0",
"GroupSet": [{ "Ref" : "WebApplicationServerSG" }]
}
]
}
}
}
}
I tried to diagnose it but failed to understand which particular configuration in this simple template is not supported currently. Any help or pointer would be greatly appreciated.
Your VPC has an instance tenancy of dedicated, however t2 instances cannot be launched as dedicated instances. You will need to pick a different instance type or switch the tenancy of your VPC.
In my case I didn't have tenancy dedicated. The reason was I tried to use the instance type which is too new (r6g) and is missing in my region. So the solution was to fall back to older one (r5a).
Looks problem with subnet creation with fn::select function.
"DevSubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : { "Ref" : "DevVpc" },
"CidrBlock" : "172.31.0.0/16",
"AvailabilityZone" : {
"Fn::Select" : [ "0", { "Fn::GetAZs" :""} ]
}
}
}
Try this. I hope it will work.

Update existing security group when creating new ec2 CloudFormation

I have ec2 instance which was created using such cfn template:
Parameters:
"VPCId": {
"Type": "AWS::EC2::VPC::Id"
"Description": "The VPC Id to where this instance is being created"
}
"Subnet": {
"Description": "Subnet to put Instance",
"Type": "AWS::EC2::Subnet::Id",
},
Have the following Security Group:
"InstanceSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Enables access to instance by port 80",
"VPCId": {
"Ref": "VPCId"
},
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": {
"Ref": "ClientCIDR"
}
}
]
},
And part of Instance Resource:
"WebServer": {
"Type": "AWS::EC2::Instance",
"Properties": {
"IamInstanceProfile": "access-profile",
"SecurityGroupIds": [
{ "Fn::GetAtt": [
"InstanceSecurityGroup",
"GroupId"
]
}
],
"SubnetId": {
"Ref": "Subnet"
},
I want to create a few another instances using another template. This instances should have access to the above instance by port 22 and connect to it in UserData.
I'm not sure how it can be organized, the one way i see is update security group using aws cli through UserData before establishing ssh connection to the first instance. How it can be organized using resources? I didn't find any information or examples regarding this. Please help! Thanks!
You can modify the InstanceSecurityGroup to allow access from the other instances:
"InstanceSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Enables access to instance by port 80",
"VPCId": {
"Ref": "VPCId"
},
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "80",
"ToPort": "80",
"CidrIp": {
"Ref": "ClientCIDR"
}
},
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"SourceSecurityGroupId": {
"Ref": "OtherInstancesSecurityGroup"
}
}
]
},
where OtherInstancesSecurityGroup is a new Security Group you will assign the the other instances.

How to add multiple security groups and group names in cloudformation using template?

"dbxSG":
{
"Type": "AWS::EC2::SecurityGroup",
"Properties":
{
"GroupDescription": "Enable dbX Access",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": "22",
"ToPort": "22",
"CidrIp": "0.0.0.0/0"
}
]
}
},
"dbxSGIngress" :
{
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties":
{
"GroupName": { "Ref": "dbxSG" },
"IpProtocol": "tcp",
"FromPort": "0",
"ToPort": "65535",
"SourceSecurityGroupName": { "Ref": "dbxSG" }
}
},
How do I add multiple security group names in above json file? "dbxSG" name is referring in many times. I want to add one more security group with a new name. How do I add it?
Yes, you can attach multiple Security Groups to an EC2 Instance when created using CloudFormation. Below is sample json to accomplish it. I have attached WebSubnetSG & AppSubnetSG to the EC2 Instance.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Multiple Security Groups - Demo",
"Resources" : {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16" ,
"Tags": [
{
"Key": "Name",
"Value": "Multi Security Group"
}
]
}
},
"WebSubnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"CidrBlock": "10.0.10.0/24",
"Tags": [
{
"Key": "Application",
"Value": "Multi SG Subnet"
}]
}
},
"WebServerSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "SG for the Web Server",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupEgress": [
{
"IpProtocol": "-1",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupIngress" : [
{
"IpProtocol": "tcp",
"CidrIp": "0.0.0.0/0",
"FromPort": "80",
"ToPort": "80"
},
{
"IpProtocol": "tcp",
"CidrIp": "0.0.0.0/0",
"FromPort": "443",
"ToPort": "443"
}
]
}
},
"AppServerSGIngress": {
"Type": "AWS::EC2::SecurityGroupIngress",
"Properties": {
"GroupId": {
"Ref": "AppServerSG"
},
"IpProtocol": "tcp",
"CidrIp": "0.0.0.0/0",
"FromPort" : "9090",
"ToPort" : "9090"
}
},
"AppServerSG": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "SG for the App Server",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupEgress": [
{
"IpProtocol": "-1",
"CidrIp": "0.0.0.0/0"
}
],
"SecurityGroupIngress" : [
{
"IpProtocol": "tcp",
"CidrIp": "0.0.0.0/0",
"FromPort": "8080",
"ToPort": "8080"
}
]
}
},
"MultiSGInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-12345678",
"KeyName": "your-key-pair",
"SecurityGroupIds": [
{
"Ref": "WebServerSG"
},
{
"Ref": "AppServerSG"
}
],
"InstanceType": "t2.micro",
"SubnetId": {
"Ref": "WebSubnet"
},
"Tags": [
{
"Key": "Name",
"Value": "MultiSG"
}
]
}
}
},
"Outputs" : {}
}