I am trying to use AWS cloudformation to create a stack with an ALB and an ECS service, but i get a CREATE_FAILED on the AWS::ECS::Service, which is elb name longer than 32.
I don’t get why the ECS Service is complaining about the ELB name while the ALB itself is in CREATE_COMPLETE status…
Here is the JSON related to the ALB creation i send to cloudformation:
"loadBalancer" : {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"Name": "test-alb",
"Scheme" : "internal",
"Subnets" : [
"subnet-b8217295",
"subnet-ddaad2b8",
"subnet-6d71fb51"
],
"LoadBalancerAttributes" : [
{ "Key" : "idle_timeout.timeout_seconds", "Value" : "50" }
],
"SecurityGroups": [
{ "Ref": "InstanceSecurityGroupOpenWeb" },
{ "Ref" : "InstanceSecurityGroupOpenFull" }
],
"Tags" : [
{ "Key" : "key", "Value" : "value" },
{ "Key" : "key2", "Value" : "value2" }
]
}
}
And here is the JSON related to the ECS Service creation (with a ref to the ALB defining above):
"EcsService": {
"Type":"AWS::ECS::Service",
"Properties":{
"Cluster":{
"Ref": "EcsCluster"
},
"DesiredCount":"1",
"DeploymentConfiguration":{
"MaximumPercent":100,
"MinimumHealthyPercent":0
},
"LoadBalancers": [
{
"ContainerName": "test-web",
"ContainerPort":"80",
"LoadBalancerName":{
"Ref": "loadBalancer"
}
}
],
"Role":{
"Ref": "EcsServiceRole"
},
"TaskDefinition":{
"Ref": "runWebServerTaskDefinition"
}
}
}
And as you can see i set the name of the ALB by myself and it is only 8 characters, so i really don’t get the point, any idea?
When you do "Ref", it would return the Load balancer ARN not the Load balancer name. you need to use GetAtt to get the load balancer name
{ "Fn::GetAtt" : [ "loadBalancer", "LoadBalancerName" ] }
Related
I want to add multiple Principal values for a KMS key using CloudFormation. This is a snippet of the code:
"KmsKeyManager": {
"Type": "String",
"Default": "user1,user2,user3"
}
"Principal": {
"AWS": {
"Fn::Split": [
",",
{
"Fn::Sub": [
"arn:aws:iam::${AWS::AccountId}:user/people/${rest}",
{
"rest": {
"Fn::Join": [
"",
[
"arn:aws:iam::",
{
"Ref": "AWS::AccountId"
},
":user/people/",
{
"Ref": "KmsKeyManager"
}
]
...
The ARN should be constructed as arn:aws:iam::12345678:user/people/user1 etc.
The template is accepted in the console, but when running I get the following error:
Resource handler returned message: "An ARN in the specified key policy is invalid.
I followed the answer here which resulted in the above error
CloudFormation Magic to Generate A List of ARNs from a List of Account Ids
Any idea where I am going wrong? CloudFormation is new to me, so the alternative is I create with 1 user and add new users manually.
Let me explain from the answer you linked. They use the string ":root,arn:aws:iam::" as a delimiter.
Therefore,
"Accounts" : {
"Type" : "CommaDelimitedList",
"Default" : "12222234,23333334,1122143234,..."
}
"rest": {
"Fn::Join": [
":root,arn:aws:iam::",
{ "Ref": "Accounts" }
]
}
gives rest like this.
12222234:root,arn:aws:iam::23333334:root,arn:aws:iam::1122143234
and this rest is substituted for ${rest} in "arn:aws:iam::${rest}:root" (This long string will be split finally with "Fn::Split".)
In your case, delimiter will be "arn:aws:iam::${AWS::AccountId}:user/people/".
This is also need to be joined:
{
"Fn::Join": [
"", [
"arn:aws:iam::",
{
"Ref": "AWS::AccountId"
},
":user/people/"
]
]
}
The total will be like:
"Fn::Sub": [
"arn:aws:iam::${AWS::AccountId}:user/people/${rest}",
{
"rest": {
"Fn::Join": [
"Fn::Join": [
"", [
"arn:aws:iam::",
{
"Ref": "AWS::AccountId"
},
":user/people/"
]
],
{
"Ref": "KmsKeyManager"
}
]
}
}
]
I am trying to launch an ec2 instance using cloudformation.I created this json template but I get error Template format error: At least one Resources member must be defined.
{
"Type" : "AWS::EC2::Instance",
"Properties" : {
"ImageId" : "ami-08ddb3f251a88cf33",
"InstanceType" : "t2.micro ",
"KeyName" : "Stagingkey",
"LaunchTemplate" : {
"LaunchTemplateId" : "jen1",
"LaunchTemplateName" : "Launchinstance",
"Version":"V1"
},
"SecurityGroupIds" : [ "sg-055f49a32efd4238b" ],
"SecurityGroups" : [ "jenkins_group" ],
}
}
What am I doing wrong?
Is there any other template for ap-south-1 region which I could use? Any help would be appreciated.
The error says it all: At least one Resources member must be defined.
The major sections of a template are:
Parameters
Mappings
Resources
Outputs
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "My Stack",
"Resources": {
"MyInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-08ddb3f251a88cf33",
"InstanceType": "t2.micro ",
"KeyName": "Stagingkey",
"LaunchTemplate": {
"LaunchTemplateId": "jen1",
"LaunchTemplateName": "Launchinstance",
"Version": "V1"
},
"SecurityGroupIds": [
"sg-055f49a32efd4238b"
],
"SecurityGroups": [
"jenkins_group"
]
}
}
}
}
You'll need to test it. For example, it is unlikely that you will define both SecurityGroupIds and SecurityGroups.
All the properties you have entered are properties of an EC2 resource, which you need to declare. You have no resources block/a logical name for you resource, like so:
"Resources": {
"MyTomcatName": {
"Type": "AWS::EC2::Instance",
"Properties": {
[...]
I am trying to deploy an ECS stack with an ALB using cloudformation, and i get an error at the Service creation, which seems to be a missing permission to access the load balancer.
Here is the error: Unable to assume role and validate the specified targetGroupArn. Please verify that the ECS service role being passed has the proper permissions.
Here is the service definition:
"EcsService": {
"Type":"AWS::ECS::Service",
"DependsOn": [
"loadBalancer",
"EcsServiceRole"
],
"Properties":{
"Cluster":{
"Ref": "EcsCluster"
},
"DesiredCount":"1",
"DeploymentConfiguration":{
"MaximumPercent":100,
"MinimumHealthyPercent":0
},
"LoadBalancers": [
{
"ContainerName": "test-web",
"ContainerPort": "80",
"TargetGroupArn" : {
"Ref": "loadBalancer"
},
}
],
"Role":{
"Ref": "EcsServiceRole"
},
"TaskDefinition":{
"Ref": "runWebServerTaskDefinition"
}
}
}
Here is the Load Balancer definition:
"loadBalancer" : {
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer",
"Properties": {
"Name": "testalb",
"Scheme" : "internal",
"Subnets" : [
"subnet-b8217295",
"subnet-ddaad2b8",
"subnet-6d71fb51"
],
"LoadBalancerAttributes" : [
{ "Key" : "idle_timeout.timeout_seconds", "Value" : "50" }
],
"SecurityGroups": [
{ "Ref": "InstanceSecurityGroupOpenWeb" },
{ "Ref" : "InstanceSecurityGroupOpenFull" }
],
"Tags" : [
{ "Key" : "key", "Value" : "value" },
{ "Key" : "key2", "Value" : "value2" }
]
}
}
Here is the IAM role the service should use:
"EcsServiceRole": {
"Type":"AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement":[
{
"Effect":"Allow",
"Principal":{
"Service":[
"ecs.amazonaws.com"
]
},
"Action":[
"sts:AssumeRole"
]
}
]
},
"Path":"/",
"Policies":[
{
"PolicyName":"ecs-service",
"PolicyDocument":{
"Statement":[
{
"Effect":"Allow",
"Action":[
"elasticloadbalancing:*",
"ec2:*"
],
"Resource":"*"
}
]
}
}
]
}
}
I didn't find if there is a specific namespace for ALB in IAM.
Do you have an idea?
TargetGroupArn should be pointing to TargetGroup ARN, not ALB ARN, Currently, it is pointed to Load Balancer ARN.
"TargetGroupArn" : {
"Ref": "loadBalancer"
},
UPDATE:
As of July 19th 2018, it is now possible to create a IAM Service-Linked Roles using CloudFormation https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-servicelinkedrole.html.
EcsServiceLinkedRole:
Type: "AWS::IAM::ServiceLinkedRole"
Properties:
AWSServiceName: "ecs.amazonaws.com"
Description: "Role to enable Amazon ECS to manage your cluster."
OLD ANSWER:
Since AWS introduced Service-Linked Roles, I no longer specify a role for my AWS::ECS::Service. It will default to the service linked role which has all the necessary permissions.
I have defined my parameters like this:
{
"PrivateSubnets":{
"Description":"db subnetlist",
"Type": "List<AWS::EC2::Subnet::Id>"
},
"VPCLIST": {
"Description": "VPC list",
"Type": "List<AWS::EC2::VPC::Id>"
}
}
and referring the above parameters in "resources" section like below:
"InstanceSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"VpcId" : {"Ref": "VPCLIST"} ,
"GroupDescription" : "Enable 3306/80/SSH access via port 22"
}
and while executing this I am getting the below error.
AWS::EC2::SecurityGroup InstanceSecurityGroup "Value of property VpcId must be of type String"
Note: I have only default VPC available which is not taken as string? any solutions to this issue...
The correct way is make this change:
{
"PrivateSubnets": {
"Description":"db subnetlist",
"Type": "AWS::EC2::Subnet::Id"
},
"VPCLIST": {
"Description": "VPC list",
"Type": "AWS::EC2::VPC::Id"
}
}
The Security Groups requires the VpcId to be a string, the property is an array list, So you need to change the property to Type: String, or use the
Fn::Select function.
{ "Fn::Select" : [ 0, VPCLIST ] }
List – An array of VPC IDs
{
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupName" : String,
"GroupDescription" : String,
"SecurityGroupEgress" : [ Security Group Rule, ... ],
"SecurityGroupIngress" : [ Security Group Rule, ... ],
"Tags" : [ Resource Tag, ... ],
"VpcId" : String
}
}
http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html
In the AWS Resource AWS::ApplicationAutoScaling::ScalableTarget, how do I retrieve the value of ResourceId which is the unique resource identifier that associated with the scaleable target?
The format used in the ResourceId property is service/cluster_name/service_name.
You are correct that the ResourceId property should be in the form service/<cluster_name>/<service_name>.
Incidentally, (and to help future Googlers) the error message that you get when you use an incorrect ResourceId or ScalableDimension is:
Unsupported service namespace, resource type or scalable dimension
To achieve this in CloudFormation you can use a Fn::Join for the ResourceId. Here is a snippet of the Scalable target that I am using:
"ECSServiceScalableTarget": {
"Type": "AWS::ApplicationAutoScaling::ScalableTarget",
"Properties": {
"MaxCapacity": 5,
"MinCapacity": 1,
"ResourceId": { "Fn::Join" : ["/", [
"service",
{ "Ref": "ECSCluster" },
{ "Fn::GetAtt" : ["ECSService", "Name"] }
]]},
"RoleARN": { "Fn::Join" : ["", ["arn:aws:iam::", { "Ref" : "AWS::AccountId" }, ":role/ApplicationAutoscalingECSRole"]]},
"ScalableDimension": "ecs:service:DesiredCount",
"ServiceNamespace": "ecs"
}
}
I use the {"Fn::Join" : [ ":", [ "a", "b", "c" ] ]"} to get the value of the "ResourceId".