Cloudformation SubnetList get CidrBlock - amazon-web-services

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.

Related

Cloud formation failed to create Security group with VPCIdNotSpecified

Problem :
While creating Security group using cloud formation template, it fails with VPCIdNotSpecified error even though I have provided VPCID as an input.
Error Message:
No default VPC for this user (Service: AmazonEC2; Status Code: 400; Error Code: VPCIdNotSpecified; Request ID: d45efd39-16ce-4c0c-9e30-746b39f4ff44; Proxy: null)
Background :
I have deleted the default VPC that comes with the account and created my own VPC. Also, I am getting the VPC ID as a parameter input. \1/used aws cli to verify the template and its good.
All the input parameters were fetch correctly and shown in summary page of cloud formation creation. It even shows the VPCID which is matched.
Code :
Parameters:
VPCName:
Description: Enter the VPC that you want to launch the instance
Type : AWS::EC2::VPC::Id
ConstraintDescription: VPC must be already existing
Resources:
HANASG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: XSASG
GroupDescription: This will allow connections between your RDP instance & HANA Box
**VpcId: !Ref VPCName**
SecurityGroupIngress:
- IpProtocol: tcp
SourceSecurityGroupName: !Ref RdpSgName
FromPort: 0
ToPort: 65535
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 0
ToPort: 65535
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: HANAXSASG```
I would suggest re-creating the default VPC in the VPC section of the console per amazons instructions. Its a good idea NOT to use the default VPC and to create and configure your own as you describe. Internally there is something special about the default VPC that is not exposed via the console or API. I suspect that is the root cause of your issue, and creating a new default VPC should fix it.
AFAIK theres no issue in renaming the default VPC (mine are named Default VPC - DO NOT USE).
The scope of a SG is limited within a VPC. So its a mandatory field while creating a SecurityGroup to specify a value for VpcId .
It may be an item under EC2 buts its scope is within a VPC. You cannot create a SG without specifying a VPC. Just like you cant create an EC2 without specifying its Subnet and VPC.
Can you remove ** and try?

AWS: Network ACL configured to accept traffic only from another Network ACL

I am pretty new to CloudFormation. I am creating a VPC, Subnets and security groups. I would also want to create an ACL for each subnet in my VPC.
From what I understand, ACL is a way to assign a firewall rule to all the resources that are held by a given subnet. Please, correct me if i am wrong.
The problem is that i would like to configure an ACL so that all the resources within it can only accept traffic from resources within another ACL.
I know it is possible to create a security groups that only accepts traffic from another security group.
My CloudFormation template would be:
webSubnetACL:
Type: 'AWS::EC2::NetworkAcl'
Properties:
VpcId: !Ref managementVpc
webSubnetAssociation:
Type: 'AWS::EC2::SubnetNetworkAclAssociation'
Properties:
NetworkAclId: !Ref webSubnetACL
SubnetId: !Ref webSubnet
fromWorldHTTP:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref webSubnetACL
RuleNumber: '300'
Protocol: '6'
PortRange:
From: 80
To: 80
RuleAction: allow
CidrBlock: 0.0.0.0/0
fromWeb:
Type: 'AWS::EC2::NetworkAclEntry'
Properties:
NetworkAclId: !Ref dbSubnetACL
RuleNumber: '102'
Protocol: '6'
PortRange:
From: 3600
To: 3600
RuleAction: allow
CidrBlock: 10.0.0.0/25
So in this case there would be 2 subnets : webSubnet, that will hold web servers, and dbSubnet that will hold databases THAT MUST GRANT CONNECTION ONLY TO resources in webSubnet.
In fromWeb resource i am not able to reference the fromWorldHTTP resource.
Unfortunately you cannot reference any AWS logical resources in your NACL rules (such as a NACL, ENI or Security Group).
If you want to whitelist you must add an explicit CIDR range of the subnets that you want to allow ingress/egress connections for.
If any of the subnet ranges are together you may be able to supernet the ranges together to reduce the number of rules.
i am not able to reference the fromWorldHTTP resource.
You can't do this, because its not possible. NACLs can't reference other NACLs. In contrast SGs can reference other SGs, as you pointed out.
NACL rules are soley based on IP addresses and IP ranges. Thus, you have to reference IP ranges only in your NACLs.

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.

How to get CidrBlock value from VPC object input to cloudformation?

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.

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