How to get CidrBlock value from VPC object input to cloudformation? - amazon-web-services

I have a cloudformation template. I take as input a VPC. I want to get the CidrBlock value from the VPC input. How can I do this?
I can take AWS::EC2::VPC::Id as an input, but this appears to simply be a reference to the physical ID. I tried to take AWS::EC2::VPC as input, but it appears this type is not recognized by cloud formation.
Here is my code:
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
pVpc:
Description: "The VPC"
Type: AWS::EC2::VPC::Id
Resources:
rSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref pVpc
SecurityGroupIngress:
- IpProtocol: -1
CidrIp: "0.0.0.0/0"
# !GetAtt pVpc.CidrBlock # <-- How can I do this?

You cannot do that unless you deploy Lambda backed custom resource that will take your VPC Id as input and return associated CIDR block.
Other option is to export CIDR block from the CFT that created the VPC and reference that exported variable in your current CFT.

Related

How to reference existing resources in CloudFormation yaml template?

I want to only create the EC2 instance for automation purposes but to point to existing VPC, Subnet, Security groups and Internet Gateway.
Does anyone know what would it look like in the template file?
My current template looks like this. It fails when creating the stack and the instance is deleted automatically.
The error I received is CREATE_FAILED with the description "No default VPC for this user. GroupName is only supported for EC2-Classic and default VPC."
AWSTemplateFormatVersion: 2010-09-09
Parameters:
VPCId:
Type: AWS::EC2::VPC::Id
Resources:
MySubnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPCId
EC2Instance:
Type: AWS::EC2::Instance
Properties:
ImageId: ami-04ff9e9b51c1f62ca
InstanceType: c5.xlarge
KeyName: CloudFormation
SecurityGroupIds:
- mySecurityGroup
Edited with template
SecurityGroupIds should be ID, not name. The security group IDs have format of sg-xxxxxxxxx, and that's what you have to use.

My Cloudformation YAML for autoscaling group keeps creating EC2 instances in default VPC even after I specify a custom VPC

My Cloudformation YAML for autoscaling group keeps creating EC2 instances in default VPC even after I specify a custom VPC. Here's the snippets of code:
TargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Port: 80
Protocol: HTTP
VpcId: !Ref VpcId
Parameters section:
VpcId:
Description: Enter the VpcId
Type: AWS::EC2::VPC::Id
Default: vpc-0ed238eeecc11b493
I keep seeing termination of EC2 instances because the launch config is for some reason creating the instances in the default VPC even through I have specified to use the custom in the parameters section. I dont know why it is not taking the custom VPC. When I check security groups, launch config in the AWS console it shows the custom VPC but when I check the EC2 instance launched by the auto scaling group, I see the default VPC.
My default VPC is vpc-6a79470d and my custom VPC is vpc-0ed238eeecc11b493
The error I see in the Autoscaling group section of the console is:
Description:DescriptionLaunching a new EC2 instance: i-041b680f6470379e3.
Status Reason: Failed to update target group arn:aws:elasticloadbalancing:us-west-1:targetgroup/ALBTe-Targe-7DMLWW46T1E6/f74a31d17bf3c4dc:
The following targets are not in the target group VPC 'vpc-0ed238eeecc11b493': 'i-041b680f6470379e3' Updating load balancer configuration failed.
Hope someone can help point out what I am doing wrong. I see in AWS documentation that ASG by default launches in default VPC but there must be a way to do it in CloudFormation if it is possible to do it through console.
=============================== After update==========================
Here's how it looks now after adding VPCZoneIdentifier, not sure what I am doing wrong and getting an issue with security group now
AutoScalingGroup:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
AvailabilityZones: !GetAZs
VPCZoneIdentifier: !Ref SubnetIds
LaunchConfigurationName: !Ref LaunchConfiguration
MinSize: 1
MaxSize: 3
TargetGroupARNs:
- !Ref TargetGroup
LaunchConfiguration:
Type: AWS::AutoScaling::LaunchConfiguration
Properties:
KeyName: !Ref KeyName
InstanceType: t2.micro
SecurityGroups:
- !Ref EC2SecurityGroup
ImageId:
Fn::FindInMap:
- RegionMap
- !Ref AWS::Region
- AMI
LaunchConfiguration --region ${AWS::Region}
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: ALB Security Group
VpcId: VpcId: !Ref VpcId
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
EC2SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: EC2 Instance
In your ASG you usually would define VPCZoneIdentifier:
A list of subnet IDs for a virtual private cloud (VPC). If you specify VPCZoneIdentifier with AvailabilityZones, the subnets that you specify for this property must reside in those Availability Zones.
The example is as follows:
Parameters:
SubnetIds:
Type: List<AWS::EC2::Subnet::Id>
Description: Subnet IDs for ASG
Resources:
MyASG:
Type: AWS::AutoScaling::AutoScalingGroup
Properties:
# ... other properties
VPCZoneIdentifier: !Ref SubnetIds
The snippet you are providing is for the target group of the load balancer.
This error will occur because the subnets attached to your auto scaling group are not within the same VPC as your target group.
Use a parameter type of List<AWS::EC2::Subnet::Id> to specify the subnets for your autoscaling group.
For your autoscaling group the VPCZoneIdentifier parameter should be assigned the values of the parameter.
More information is available here for this parameter type.

Access to IPv4 CIDR of a subnet passed as parameter in CloudFormation template

I'm passing as a parameter a "Subnet ID"
VPCPrivateSubnet1:
Description: VPCPrivateSubnet1
Type: String
Default: 'subnet-83733e21'
Then, I'm creating a "Security Group"
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPCid
GroupDescription: Security Group
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 10
ToPort: 10
CidrIp: ???
And for the CidrIp I would like to have a way to refer to it without having to type it. Something like VPCPrivateSubnet1.CidrIp. I don't have the Subnet exported (so I can import it). I am not creating it in the template, so I cannot use Ref.
I will appreciate help.
Unfortunately this is not easily achievable. But even if you had your subnet defined in the same template as your security group, or exported from other stack, AWS::EC2::Subnet can't return its CIDR.
However, you could design Custom Resource in CloudFormation which would give you the CIDR of a subnet you want.
For this you would have to write your own custom lambda function, which would take the subnet's id and using, e.g., boto3 SDK, return the CIDR into CloudFormation.
Having this you could do !GetAtt CustomGetSubnetInfoResource.CidrIp, where CustomGetSubnetInfoResource could be the name of your custom resource.

Cloudformation SubnetList get CidrBlock

I'm working on a new infrastructure provisioned with CloudFormation. I need to fetch a subnet cidrblock for the security groups.
I've tried some method for fetch the subnet Cidr blocks but I'm getting the following error:
YAML not well-formed
My template is:
SubnetList:
Description: 'Gateway Subnet Id'
Type: List<AWS::EC2::Subnet::Id>
.....
..
....
ElastiCacheSecurityGroupIngressGateway: ##SubnetLists
Type: AWS::EC2::SecurityGroupIngress
Properties:
GroupId: !GetAtt SecGroup.GroupId
IpProtocol: tcp
FromPort: '6379'
ToPort: '6379'
CidrIp: Fn::GetAtt: [ Fn::Select: [ 0, !Ref SubnetList ], CidrBlock ]
I need the fetch cidr block from SubnetList.
How I can handle this?
I don't think you can do this unless you created the subnets within this same template. When using GetAtt you need to supply the name of a resource within the CloudFormation template. You're simply providing a parameter list of subnet IDs - those are strings, not CloudFormation-managed resources.
You could simply pass in the subnet CIDRs as parameters or, better still, reference them as outputs from the stack that created the VPC and subnets in the first place using Fn::ImportValue.
Also see this proposed solution to the very same problem. Caveat: it's not trivial.

Is there a way to reference a security group from a previous Cloudformation stack in a new CF stack?

I'm trying to build a stack with multiple EC2 instances that have varied security groups.
It would be easy for me if I could create my security groups in advance and reference them in my EC2 stack.
Is there a way to reference an existing security group resource in a CF stack?
Thanks in advance for the help!
yes this is totally possible with standard Cloudformation templates.
You can solve this in a couple of ways.
If you are using nested stacks, you can create all the security groups you need in one sub-stack. That stack should have Outputs for each of the Security Group Ids you created.
Outputs:
SecurityGroup1Id:
Description: Security Group 1 ID
Value: !Ref SecurityGroup1
In the stack that then creates your EC2 instances, you can define Parameters for each of the security Groups. It can either be an array or one parameter for each Group, depending on your use case.
Single Template
If the EC2 instances and security groups are being defined in the same template, then you can use a simple Ref to access the ID of the already created security group. ie: !Ref SecurityGroup1Name
If you already have a security group deployed and you know the Id of it you can reference it like this under Properties.
You can reference multiple security groups, as it is a list
SecurityGroupIds:
- <the id of the security group>
- <another security group ID>
Yes, you can cross reference outputs from a stack in another.
Here is a walkthrough from the AWS official documentation.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/walkthrough-crossstackref.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference-importvalue.html
If the Security Groups were created outside of CloudFormation (Console/CLI) or the CloudFormation stacks aren't linked via nesting or exports, you should define them as Parameters, then reference that parameter name in your template:
Parameters:
MySecurityGroup:
Type: String
Description: ID of an existing VPC security group (sg-xxxxxx)
Resources:
MyInstance:
Type: AWS::EC2::Instance
Properties:
# All of your other properties
SecurityGroupIds:
- !Ref MySecurityGroup
If the security group ID is something you're going to reference often, put it in SSM Parameter Store and link the two by following the steps in this blog post: https://aws.amazon.com/blogs/mt/integrating-aws-cloudformation-with-aws-systems-manager-parameter-store/
Yes, you can create a security group in advance and refer them into the new stack.
In the below example we are creating a securty group through cloudformation template to allowing 3389/RDP Protocol for user(user name is User1) and exporting security group
name.
And in EC2 CloudFormation stack we are importing the exported value(sg name) of security group CloudFormation stack.
AWSTemplateFormatVersion: 2010-09-09
Description: CloudFormation template for Security Group definitions
Parameters:
User1:
Description: Public IP OF Deven .
Type: String
Default: 106.209.184.29/32
AllowedPattern: (\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})
ConstraintDescription: Must be valid IP Range.
Resources:
MySG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Common Jenkins SG.
VpcId: vpc-8587d522
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 3389
ToPort: 3389
CidrIp: !Ref User1
Description: User1 - RDP access .
- Key: Name
Value: test-security-group
SecurityGroupEgress: []
Outputs:
Ec2SecurityGroup:
Description: Security Group ID for EC2
Value: !Ref MySG
Export:
Name: !Sub "${AWS::StackName}-testapplication"
In Youe EC2 instance template import the value . below is the example for the same.
Type: 'AWS::EC2::Instance'
Properties:
.
.
(your other parameters mentioned in 'AWS::EC2::Instance' )
.
.
KeyName: !Ref Key
SubnetId: !Ref SubnetA
SecurityGroups:
Fn::ImportValue:
!Sub "${SGStackName}-RenderEngine" ##### SGStackName is Security group CloudFormation Stack name
.
.
(your other parameters mentioned in 'AWS::EC2::Instance' )
.
.
For more detail please gough with official link