I am trying to create a CloudFormation template that accepts an optional SSH key pair as a parameter. I want to use the AWS::EC2::KeyPair::KeyName
type so the CloudFormation interface gives the user a list of available keys like in the picture.
The problem I'm having is with the optional part. If the user leaves the selection empty, the default value is used but is not considered valid. I get:
Parameter validation failed: parameter value for parameter name SSHKey does not exist. Rollback requested by user.
Is there a way to define a parameter that can be left empty but has a non-generic type?
Here's a sample template that shows the problem:
{
"Parameters": {
"SSHKey": {
"Type": "AWS::EC2::KeyPair::KeyName",
"Description": "Leave empty to disable SSH",
"Default": ""
}
},
"Conditions": {
"EnableSSH": {
"Fn::Not": [
{
"Fn::Equals": [
"",
{
"Ref": "SSHKey"
}
]
}
]
}
},
"Resources": {
"LaunchConfig": {
"Type": "AWS::AutoScaling::LaunchConfiguration",
"Properties": {
"ImageId": "ami-9eb4b1e5",
"InstanceType": "t2.micro",
"KeyName": {
"Fn::If": [
"EnableSSH",
{
"Ref": "SSHKey"
},
{
"Ref": "AWS::NoValue"
}
]
},
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": "8"
}
}
]
}
}
}
}
Kindly find the template based on your condition.
{
"Parameters":{
"SSHKey":{
"Type":"AWS::EC2::KeyPair::KeyName",
"Description":"select the keypair SSH",
"Default":""
},
"KeyPairRequired":{
"Type":"String",
"AllowedValues":[
"yes",
"no"
],
"Description":"Select yes/no whether to Add key pair to instance or not."
}
},
"Conditions":{
"CreateLCWithKeyPair":{
"Fn::Equals":[
{
"Ref":"KeyPairRequired"
},
"yes"
]
},
"CreateLCWithoutKeyPair":{
"Fn::Equals":[
{
"Ref":"KeyPairRequired"
},
"no"
]
}
},
"Resources":{
"LaunchConfigWithKey":{
"Condition":"CreateLCWithKeyPair",
"Type":"AWS::AutoScaling::LaunchConfiguration",
"Properties":{
"ImageId":"ami-9eb4b1e5",
"InstanceType":"t2.micro",
"KeyName":{
"Ref":"SSHKey"
},
"BlockDeviceMappings":[
{
"DeviceName":"/dev/xvda",
"Ebs":{
"VolumeSize":"8"
}
}
]
}
},
"LaunchConfigWithoutKey":{
"Condition":"CreateLCWithoutKeyPair",
"Type":"AWS::AutoScaling::LaunchConfiguration",
"Properties":{
"ImageId":"ami-9eb4b1e5",
"InstanceType":"t2.micro",
"BlockDeviceMappings":[
{
"DeviceName":"/dev/xvda",
"Ebs":{
"VolumeSize":"8"
}
}
]
}
}
}
}
The AWS::EC2::KeyPair::KeyName
parameter falls under AWS-Specific Parameter Type and as per the AWS docs and suggestions, the template user must specify existing AWS values that are in their account.
It's not possible to leave the SSHKey empty in your CloudFormation template. Kindly refer to the CloudFormation Parameter Syntax. Under the AWS Specific Parameter Types section of that document, you will find the following:
For AWS-specific parameter types, template users must specify existing
AWS values that are in their account. AWS CloudFormation supports the
following AWS-specific types
If you have a small number of SSH Keys in your account, and you don't change them very often, one thing you could do is use the Type: String
, and in it include an AllowedValues
property. For example:
"Parameters": {
"SSHKey": {
"Type": "String",
"Description": "Leave empty to disable SSH",
"Default": "",
"AllowedValues: ["","Project1Beanstalk","Project2Beanstalk"]
}
},
"Conditions": {
"EnableSSH": {
"Fn::Not": [
{
"Fn::Equals": [
"",
{
"Ref": "SSHKey"
}
]
}
]
}
This would mean that you'd have to update the template any time that a new SSH Key is added, but add the nice Dropdown similar to the one you mentioned, and has the option of not configuring a key as you requested.