For some reason, I thought I could stack multiple ingress and egress rules in a single AWS::EC2::SecurityGroup (AWS CloudFormation template) this way:
# Wrong !!
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Open HTTP (port 80) and SSH (port 22)"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Sub "${MyIp}"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Even though this did not throw an error, the AWS console’s view of Ingress (Inbound) showed only one rule, not the two I declared:

Where’s my port 22 ingress rule?!!
Through trial and error, I realized I had formatted the template wrong. SecurityGroupIngress and SecurityGroupEgress properties are lists. I was treating them as individual entries. In other words, I need to list the multiple Ingress rules under a single SecurityGroupIngress entry. Like this:
# Correct, Option A
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Open HTTP (port 80) and SSH (port 22)"
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: !Sub "${MyIp}"
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
Which did create the (two) Ingress and (one) Egress rules, as expected:


Another option is to declare AWS::EC2::SecurityGroupIngress and AWS::EC2::SecurityGroupEgress, attaching them to the SecurityGroup.
Note: Amazon suggests using this method “… only when necessary, typically to allow security groups to reference each other in ingress and egress rules. Otherwise, use the embedded ingress and egress rules of the security group” (such as with Option A, demonstrated above.)
# Correct, Option B
SecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: "Open HTTP (port 80) and SSH (port 22)"
VpcId: !Ref VPC
SecurityGroupIngressMySSH:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: "Allow SSH connections from MyIp"
GroupId: !Ref SecurityGroup
CidrIp: !Sub "${MyIp}"
IpProtocol: tcp
FromPort: 22
ToPort: 22
SecurityGroupIngressHTTP:
Type: AWS::EC2::SecurityGroupIngress
Properties:
Description: "Allow HTTP inbound traffic"
GroupId: !Ref SecurityGroup
CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 80
ToPort: 80
SecurityGroupEgress:
Type: AWS::EC2::SecurityGroupEgress
Properties:
Description: "Allow all outbound traffic"
GroupId: !Ref SecurityGroup
CidrIp: 0.0.0.0/0
IpProtocol: tcp
FromPort: 80
ToPort: 80
i’m looking for a way to add an ingress rule that pulls the cidr block for the vpc that the SG is being deployed to without having to manually input the cidr range of the the vpc. but i’m not sure how to do it. it appears that you have done so above.