I was wanting to write a complete CloudFormation template for a single Linux EC2 Instance in a public subnet. I used AWS CloudFormation template for creating an EC2 Instance with a Security Group as my starting point. This template launches an instance into your default VPC.
My goal was to have a self contained template that creates everything needed in a new stack but not into the default VPC. I wanted a new VPC, Security Group, Route Table, Internet Gateway, Subnet and launch a new Linux EC2 instance.
So I used the above template and added the needed resources and linked them using Ref
s. Everything created fine: VPC, Subnet, Security Group, Internet GW, RouteTables, etc. But My EC2 would error out and the the stack would roll back.
The status reason was:
Value () for parameter groupId is invalid. The value cannot be empty (Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterValue; Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx)
The EC2 resource in the CloudFormation template looked like:
"EC2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"InstanceType" : { "Ref" : "InstanceType" },
"SecurityGroups" : [ { "Ref" : "InstanceSecurityGroup" } ],
"KeyName" : { "Ref" : "KeyName" },
"ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }
}
}
The error message was not clear on what to do.
After searching on the error message, I came across many people grumbling about the vague error message, but no specific fix for the EC2 Resource in a CloudFormation template.
Some people mentioned that when you don't launch an EC2 into the default VPC, you need to specify security group ids instead of the security group names.
Checking the reference for the EC2 CloudFormation Resource type, there is this:
SecurityGroups
[EC2-Classic, default VPC] The names of the security groups. For a nondefault VPC, you must use security group IDs instead.
At the top of the page, the Security Group Ids are specified for an EC2 like so:
"SecurityGroupIds" : [ String, ... ],
So I changed my EC2 Resource to the following:
"EC2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"InstanceType" : { "Ref" : "InstanceType" },
"SecurityGroupIds" : [
{ "Fn::GetAtt" : [ "InstanceSecurityGroup", "GroupId" ] }
],
"SubnetId" : {"Ref":"TestSubnet"},
"KeyName" : { "Ref" : "KeyName" },
"ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" },
{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "InstanceType" }, "Arch" ] } ] }
}
},
and it worked.