AWS Cloud Formation RDS security group in VPC - amazon-web-services

I am trying to add ingress rules to a security group for an RDS instance, but when I add them it says The security group 'sg-14820a71' does not exist in default VPC 'vpc-527a8037'.
I have explicitly specified the VPC I want the security group in, it should not be using the default. Any idea on how to make it use the correct VPC?
"Resources": {
"DbVpcSecurityGroup": {
"DependsOn": ["VPC", "BeanstalkSecurityGroup"],
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group for RDS DB Instance.",
"VpcId": {
"Ref": "VPC"
},
"SecurityGroupIngress": [{
"IpProtocol": "tcp",
"FromPort": 3306,
"ToPort": 3306,
"SourceSecurityGroupName": {
"Ref": "BeanstalkSecurityGroup"
}
}]
}
}
}
It work fine with no ingress rules (an creating the manually in the GUI):
"Resources": {
"DbVpcSecurityGroup": {
"DependsOn": ["VPC", "BeanstalkSecurityGroup"],
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group for RDS DB Instance.",
"VpcId": {
"Ref": "VPC"
},
}
}
}
This is the beanstalk security group:
"BeanstalkSecurityGroup": {
"DependsOn": ["VPC"],
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Allow the Elastic Beanstalk instances to access the NAT device",
"VpcId": {
"Ref": "VPC"
},
}
}

While working in VPC, we should always use Security Group ID instead of Security Group Name.
So in this case of CloudFormation, use SourceSecurityGroupOwnerId instead of SourceSecurityGroupName

Related

AWS cloud formation : Inbound rules not getting added with this cloud formation template

I am learning to create stacks using cloud formation template, I am trying to create an EC2 instance using cloud formation template with security groups so I can ssh to it as well.
My cloud formation template is :
{
"Description": "Create an EC2 instance by AWS CloudFormation",
"Resources": {
"EC2instance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"AvailabilityZone": "us-east-1b",
"ImageId": "ami-08e697937cb1d2fa0",
"InstanceType": "t2.micro",
"SubnetId": "subnet-f27e50aa",
"KeyName": "DeepNewKP"
}
},
"SecurityGroupDemoSvrTraffic": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupName": "sgDemoSvr",
"SecurityGroupIngress": [
{
"IpProtocol": "tcp",
"FromPort": 22,
"ToPort": 22,
"CidrIp": "115.110.123.22/32",
"Description": "For traffic from Internet"
}
],
"GroupDescription": "Security Group for demo server",
"VpcId": "vpc-ba7ef3dd"
}
}
}
}
Stack is getting created but when I check the security groups I don't find the rule that I mentioned there. Because of this, I can't ssh to it(I am able to ssh it after adding that manually). I want to know what I am doing wrong in the template.
The only issue i see is your not attaching the security group to the instance, so add the below to the EC2instance properties:
"SecurityGroupIds": [{"Ref":"SecurityGroupDemoSvrTraffic"}]
See SecurityGroupIds section of the docs

Cloudformation script taskset cannot pull image from ECR

In my current setup I use cloudformation to setup an environment. All the steps configured so far seem to work, except for the taskset. I use an image on AWS ECR repo to launch a Fargate instance, which is put into a new cluster with a service.
When I create the stack all the steps succeed but the creation of the service is stuck in "CREATE_IN_PROGRESS" forever. When I look at the created service and more specifically the task, I found that cloudformation was unable to fetch the image. The error is as follows:
STOPPED (CannotPullContainerError: Error response from daem)
Now when I manually try to an instance using the same image on said cluster, it works just fine. After some googling I came upon certain solutions. I have implemented all of them, such as:
Create a network with security groups which allows outgoing traffic to all destinations
Set the flag AssignPublicIp to 'ENABLED' in the awsvpc configuration
Set the user execution role to the same one I used in manual creation
Note that the task does get created and it does receive a public and private IP address. Also, I have tried to throw away the ECR instance and create a new one with a new name (and of course tagged and pushed the image).
The following snippet is my service and taskset definition (renamed some sensitive info):
"MyVPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.1.0/16",
"Tags": [
{"Key":"Name", "Value":"MyVPC"
}
]
},
},
"MyInternetGateway" : {
"Type" : "AWS::EC2::InternetGateway",
"Properties" : {
}
},
"MySubPublic": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": "eu-central-1a",
"CidrBlock": "10.0.1.0/28",
"MapPublicIpOnLaunch": true,
"VpcId": {
"Ref": "MyVPC"
}
},
"DependsOn": "MyInternetGateway"
},
"MySecGroup":
{
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "My security group for all incoming and outgoing.",
"GroupName" : "MySecGroup",
"SecurityGroupEgress" : [ {
"CidrIp" : "0.0.0.0/0",
"Description" : "Allow machine to reach internet.",
"FromPort" : -1,
"IpProtocol" : -1,
"ToPort" : -1
} ],
"SecurityGroupIngress" : [ {
"CidrIp" : "0.0.0.0/0",
"Description" : "Allow machine to be reached from the entire internet.",
"FromPort" : -1,
"IpProtocol" : -1,
"ToPort" : -1
} ],
"VpcId" : {"Ref": "MyVPC"}
},
"DependsOn": "MyVPC"
},
"MyCluster": {
"Type": "AWS::ECS::Cluster",
"Properties": {
"ClusterName": "MyCluster"
},
"DependsOn": [
"MyVPC"
]
},
"MyDockerTask": {
"Type": "AWS::ECS::TaskDefinition",
"Properties": {
"ContainerDefinitions": [
{
"Cpu": 512,
"Image": "<NRHERE>.dkr.ecr.eu-central-1.amazonaws.com/mysqs",
"Memory": 1024,
"MemoryReservation": 1024,
"Name": "MyContainer"
}
],
"Cpu": "512",
"ExecutionRoleArn": "arn:aws:iam::<NRHERE>:role/ecsTaskExecutionRole",
"Family": "MyFam",
"Memory": "1024",
"NetworkMode": "awsvpc",
"RequiresCompatibilities": [
"FARGATE",
"EC2"
],
"TaskRoleArn": "arn:aws:iam::<NRHERE>:role/ecsTaskExecutionRole"
},
},
"MyService": {
"Type" : "AWS::ECS::Service",
"Properties" : {
"Cluster" : {"Fn::GetAtt": ["MyCluster", "Arn"]},
"DesiredCount" : 1,
"LaunchType" : "FARGATE",
"NetworkConfiguration" : {
"AwsvpcConfiguration" : {
"AssignPublicIp" : "ENABLED",
"SecurityGroups" : [ {"Fn::GetAtt": ["MySecGroup", "GroupId"]} ],
"Subnets" : [ {"Ref": "MySubPublic"}]
}
},
"SchedulingStrategy" : "REPLICA",
"ServiceName" : "MyService",
"TaskDefinition": {"Ref": "MyDockerTask"}
},
"DependsOn": "MySubPublic"
},
"MyTaskSet": {
"Type": "AWS::ECS::TaskSet",
"Properties": {
"Cluster": {
"Ref": "MyCluster"
},
"LaunchType": "FARGATE",
"NetworkConfiguration" : {
"AwsvpcConfiguration" : {
"AssignPublicIp" : "ENABLED",
"SecurityGroups" : [ {"Fn::GetAtt": ["MySecGroup", "GroupId"]} ],
"Subnets" : [ {"Ref": "MySubPublic"}]
}
},
"Service": {"Ref": "MyService"},
"TaskDefinition": {
"Ref": "MyDockerTask"
}
},
"DependsOn": [
"MyCluster"
]
},
None of the above provided the solution. I'm open to any suggestion/solution
From the CFN template provided I can conclude that MySubPublic has no internet access.
Specifically, I see that you are creating the following VPC-related resources:
AWS::EC2::VPC
AWS::EC2::InternetGateway
AWS::EC2::Subnet
AWS::EC2::SecurityGroup
However, the problem is the lack of:
AWS::EC2::VPCGatewayAttachment which will connect the InternetGateway to your VPC
Definitions of AWS::EC2::RouteTable and AWS::EC2::Route which will be used to make your MySubPublic route traffic to the AWS::EC2::InternetGateway.
General steps to enable internet access in a subnet are described here:
Attach an internet gateway to your VPC.
Add a route to your subnet's route table that directs internet-bound traffic to the internet gateway. If a subnet is
associated with a route table that has a route to an internet gateway,
it's known as a public subnet. If a subnet is associated with a route
table that does not have a route to an internet gateway, it's known as
a private subnet.
Ensure that instances in your subnet have a globally unique IP address (public IPv4 address, Elastic IP address, or IPv6 address).
Ensure that your network access control lists and security group rules allow the relevant traffic to flow to and from your instance.

How to pick a subnet for an Elastic Beanstalk Elastic Load Balancer via Cloudformation?

I have a VPC with both private and public Subnets, and an Elasticbeanstalk Environment which runs its instances in the private Subnet. The Elasticbeanstalk Environment also has a Classic Elastic Load Balancer, which needs to be in the public Subnet. Unfortunately, EB keeps putting it with the instances.
I've called the Load Balancer into existence using the elb options on the Environment. The relevant bit of cloudformation looks like:
"accountapienv": {
"Type": "AWS::ElasticBeanstalk::Environment",
"Properties": {
"Tier": { "Type": "Standard", Name": "WebServer" }
"OptionSettings": [
{
"ResourceName": "AWSEBAutoScalingGroup",
"Namespace": "aws:autoscaling:asg",
"OptionName": "MinSize",
"Value": "2"
},
{
"Namespace": "aws:ec2:vpc",
"OptionName": "Subnets",
"Value": { "Fn::Join": [",", [ {"Ref": "privateuseast1b"}, {"Ref": "privateuseast1c" } ] ] }
},
{
"OptionName": "CrossZone",
"Namespace": "aws:elb:loadbalancer",
"Value": true
},
{
"OptionName": "ListenerProtocol",
"Namespace": "aws:elb:listener:443",
"Value": "HTTPS"
},
If I were to invoke the balancer directly as a "Type": "AWS::ElasticLoadBalancing::LoadBalancer" object, there would be a subnets option, but then I would have a hard time pointing it as an Elastic Beanstalk Environment instance pool.
I am not willing to move my instances.
So how can I get my load balancer into a public Subnet?
Found it! It's:
{
"Namespace": "aws:ec2:vpc",
"OptionName": "ELBSubnets",
"Value": ...
}
Though why AWS treats this as a VPC option I have no idea.

Security Group not accepting in CloudFormation Template

I am trying to pass the SecurityGroup name as parameter in CloudFormation Template.While creating stack its providing me dropdown list of all security group and i am providing one but its failing with below error
"Parameter validation failed: parameter value launch-wizard-1 for parameter name SecurityGroup does not exist. Rollback requested by user."
{
"Description": "Create an EC2 instance running the latest amazon Linux AMI.",
"Parameters": {
"KeyPair": {
"Description": "The EC2 key Pair to allow SSH access to the instance",
"Type": "String"
},
"SecurityGroup": {
"Description": "Name of security group",
"Type": "AWS::EC2::SecurityGroup::GroupName"
}
},
"Resources": {
"EC2Instance": {
"Properties": {
"ImageId": "ami-0080e4c5bc078760e",
"InstanceType": "t2.micro",
"KeyName": {
"Ref": "KeyPair"
},
"SecurityGroups" : [ {"Ref" : "SecurityGroup"} ]
},
"Type": "AWS::EC2::Instance"
}
},
"Outputs": {
"InstanceId": {
"Description": "The InstanceId of newly created EC2 instance",
"Value": {
"Ref": "EC2Instance"
}
}
},
"AWSTemplateFormatVersion": "2010-09-09"
}
I tested your template (replacing the AMI and using my own Security Group name) and it worked fine.
It is possible that the instance is being launched in a different VPC to the Security Group.

How do I create an Ec2 Instance with a Public IP automatically **without** declaring an Elastic IP in cloudformation?

In AWS Cloudformation, is there any way to declare an EC2 instance in VPC with a Public IP without the need to declare an Elastic IP and attach to it?
In AWS::AutoScaling::LaunchConfiguration, you could add a property "AssociatePublicIpAddress" to say the instances will accept a Public IP automatically. I am looking for the equivalent for AWS::EC2::Instance
Below is my cloudformation snippet for creating an EC2 instance. I can't any doc that mentions how to add a public IP without having to declare an Elastic IP beforehand.
"MyEc2Instance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"IamInstanceProfile": {
"Ref": "MyEc2InstanceProfile"
},
"ImageId": {
"Fn::FindInMap": [
"MyEc2Box",
{
"Ref": "Region"
},
"ImageId"
]
},
"InstanceType": {
"Fn::FindInMap": [
"MyEc2Box",
{
"Ref": "Region"
},
"InstanceType"
]
},
"KeyName": {
"Ref": "DefaultKeyPair"
},
"Monitoring": "true",
"SecurityGroupIds": [
{
"Ref": "MyEc2SecurityGroup"
}
],
"SubnetId": {
"Ref": "MyBoxSubnet"
},
"Tags": [
{
"Key": "Name",
"Value": "MyBox"
},
]
}
},
Assuming you are starting your instance in a VPC public subnet (i.e. a subnet that has a routing table incl. a rule to send traffic to 0.0.0.0/0 to the Internet Gateway), just define AssociatePublicIpAddress property in the NetworkInterfaces group of your EC2 resource:
"NetworkInterfaces" : [{
"AssociatePublicIpAddress" : "True",
"DeleteOnTermination" : "True",
"SubnetId" : { "Ref" : "PublicSubnet" },
"DeviceIndex" : "0",
"GroupSet" : [ { "Ref" : "SecurityGroup" } ]
}],
See documentation at http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-network-iface-embedded.html
If you are starting your instance in EC2 Classic networking (non VPC), it will receive a public IP address automatically.
I see that this is an old post but i post the answer anyway it can be helpful.
In the subnet you can set : "MapPublicIpOnLaunch" to True so all the instance of this subnet will have a public IP.
MapPublicIpOnLaunch
Indicates whether instances that are launched in this subnet receive a public IP address. By default, the value is false.
Required: No
Type: Boolean
Update requires: No interruption.