Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (2023)

Table of Contents #

  1. Creating a Security Group in AWS CDK
  2. Importing an Existing Security Group in AWS CDK

Creating a Security Group in AWS CDK #

Security groups are virtual firewalls - they control the traffic that goes inand out of our EC2 instances.

They allow us to define inbound and outbound rules. Inbound traffic is trafficthat comes into the EC2 instance, whereas Outbound traffic is traffic that goesout of the EC2 instance.

By default security groups provisioned with CDK allow all outbound (egress) traffic and deny all incoming (ingress) traffic.

We are going to look at multiple examples of creating security groups andediting their inbound and outbound rules.

The code for this article is available on GitHub

Let's start by creating a VPC and a security group for a web server:

lib/cdk-starter-stack.ts

Copied!

import * as ec2 from 'aws-cdk-lib/aws-ec2';import * as cdk from 'aws-cdk-lib';export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpc = new ec2.Vpc(this, 'my-cdk-vpc', { cidr: '10.0.0.0/16', natGateways: 0, maxAzs: 3, subnetConfiguration: [ { name: 'public-subnet-1', subnetType: ec2.SubnetType.PUBLIC, cidrMask: 24, }, ], }); // 👇 Create a SG for a web server const webserverSG = new ec2.SecurityGroup(this, 'web-server-sg', { vpc, allowAllOutbound: true, description: 'security group for a web server', }); webserverSG.addIngressRule( ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow SSH access from anywhere', ); webserverSG.addIngressRule( ec2.Peer.anyIpv4(), ec2.Port.tcp(80), 'allow HTTP traffic from anywhere', ); webserverSG.addIngressRule( ec2.Peer.anyIpv4(), ec2.Port.tcp(443), 'allow HTTPS traffic from anywhere', ); webserverSG.addIngressRule( ec2.Peer.ipv4('123.123.123.123/16'), ec2.Port.allIcmp(), 'allow ICMP traffic from a specific IP range', ); }}

Let's go over what we did in the code sample:

  1. We created a VPC, by instantiating and configuring the Vpc class. Weset the natGateways prop to 0 to avoid getting charged unnecessarily.

    If you want to read more about creating VPCs, I've written another article oncreating VPCs in CDK.

  2. We created a security group for a web server. The props we passed wheninstantiating theSecurityGroupclass are:

  • vpc - the VPC, the security group will be created in
  • allowAllOutbound - whether the security group should allow all outboundtraffic. By default allowAllOutbound is set to true
  • description - a short description of the security group
  1. To allow inbound traffic we used theaddIngressRulemethod on an instance of the SecurityGroup class. The parameters we passedto the method are:
  • peer - the Source in a security group inbound rule
  • connection - the Port, Protocol and Type in a security group inboundrule
  • description - a short description of the security group rule
  1. These are the inbound rules we added to our security group:
TypeProtocolPortSource
SSHTCP220.0.0.0/0
HTTPTCP800.0.0.0/0
HTTPSTCP4430.0.0.0/0
All ICMPICMPALL123.123.0.0/16

Let's provision the VPC and the security group:

shell

Copied!

npx aws-cdk deploy

After the resources have been deployed, we can see that the inbound securitygroup rules have been applied:

(Video) Basic VPC, Security Group, EC2 in CDK

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (1)

The outbound rules allow all traffic because we've set the allowAllOutboundto true, which is also the default value:

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (2)

Let's add 2 more security groups - 1 for a backend server, and 1 for adatabase server.

The security group of the backend server will only allow requests on port8000, made from instances in the webserverSG security group.

Whereas the security group for the database server will only allow requests onport 3306, made from instances in the backendServerSG security group.

The code for this article is available on GitHub

lib/cdk-starter-stack.ts

Copied!

import * as ec2 from 'aws-cdk-lib/aws-ec2';import * as cdk from 'aws-cdk-lib';export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ... rest // 👇 Create a SG for a backend server const backendServerSG = new ec2.SecurityGroup(this, 'backend-server-sg', { vpc, allowAllOutbound: true, description: 'security group for a backend server', }); backendServerSG.connections.allowFrom( new ec2.Connections({ securityGroups: [webserverSG], }), ec2.Port.tcp(8000), 'allow traffic on port 8000 from the webserver security group', ); // 👇 Create a SG for a database server const dbserverSG = new ec2.SecurityGroup(this, 'database-server-sg', { vpc, allowAllOutbound: true, description: 'security group for a database server', }); dbserverSG.connections.allowFrom( new ec2.Connections({ securityGroups: [backendServerSG], }), ec2.Port.tcp(3306), 'allow traffic on port 3306 from the backend server security group', ); }}

Let's go over what we did in the code sample:

  1. We created a backend server security group
  2. We used theallowFrommethod on an instance of theConnectionsclass to allow inbound connections on port 8000 from instances in thewebserverSG security group. The allowFrom method takes the following 3props:
  • connectable - an object that has connection options, in our case a securitygroup

  • connection - the Port, Protocol and Type in a security group
    rule

  • description - a short description of the security group rule

  1. We created a database server security group and used the allowFrom methodto allow traffic on port 3306 from the security group of the backend server

The inbound rules for the backendServerSG look as follows:

TypeProtocolPortSource
Custom TCPTCP8000webserverSG-id

The inbound rules for the dbserverSG look as follows:

TypeProtocolPortSource
MYSQLTCP3306backendServerSG-id

The outbound rules are still the default of all traffic allowed. We will editthe outbound rules of a security group later in the article.

Let's run the deploy command:

shell

Copied!

npx aws-cdk deploy

After a deployment, the inbound rules of the backend server security group showthat it only allows traffic on port 8000 from requests made from instanceswithin the web server security group:

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (3)

(Video) AWS Cloud Development Kit (CDK) Crash Course

The security group of the database server shows that it only allows traffic onport 3306 from requests made from instances within the backend server securitygroup:

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (4)

Next, we are going to take a look at how we can edit the default outbound rulesof a security group.

Updating the Outbound Rules of Security Groups in AWS CDK #

In order to edit the outbound rules of a security group in CDK, we have to setthe allowAllOutbound prop to false, when instantiating the SecurityGroupclass.

The code for this article is available on GitHub

Let's create a security group and customize its outbound traffic rules.

lib/cdk-starter-stack.ts

Copied!

import * as ec2 from 'aws-cdk-lib/aws-ec2';import * as cdk from 'aws-cdk-lib';export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ... rest // 👇 create a SG with custom Outbound rules const customOutboundSG = new ec2.SecurityGroup(this, 'custom-outbound-sg', { vpc, allowAllOutbound: false, description: 'a security group with custom outbound rules', }); customOutboundSG.addEgressRule( ec2.Peer.ipv4('10.0.0.0/16'), ec2.Port.tcp(3306), 'allow outgoing traffic on port 3306', ); customOutboundSG.addEgressRule( ec2.Peer.anyIpv4(), ec2.Port.tcp(80), 'allow outgoing traffic on port 80', ); }}

Let's go over the code snippet.

  1. We created a security group, but this time we set the allowAllOutbound propto false. This is necessary if we are going to edit the outbound rules fora security group, otherwise, our egress rules would just get ignored
  2. We used the addEgressRule method on an instance of the SecurityGroupclass

The outbound rules we added to the security group look as follows:

TypeProtocolPortDestination
MYSQLTCP330610.0.0.0/16
HTTPTCP800.0.0.0/0

Let's deploy the changes:

shell

Copied!

npx aws-cdk deploy

If we look at the VPC management console, we can see that the outbound ruleshave been applied to the security group:

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (5)

Note that we haven't added any inbound rules to the security group, so it hasnone:

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (6)

Clean up #

To delete the resources we have provisioned, issue the destroy command:

shell

Copied!

npx aws-cdk destroy
(Video) An Introduction to AWS CDK (and why you should be using it!)

Importing an Existing Security Group in AWS CDK #

In order to import an existing security group into a CDK stack, we have to usethefromSecurityGroupIdstatic method on theSecurityGroupclass.

The code for this article is available on GitHub

Let's look at an example of importing a security group in a CDK stack:

lib/cdk-starter-stack.ts

Copied!

import * as ec2 from 'aws-cdk-lib/aws-ec2';import * as cdk from 'aws-cdk-lib';export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // 👇 import security group by ID const importedSecurityGroup = ec2.SecurityGroup.fromSecurityGroupId( this, 'imported-security-group', 'YOUR-SG-ID', {allowAllOutbound: true, mutable: true}, ); console.log('security group id 👉', importedSecurityGroup.securityGroupId); }}

Let's go over the code snippet.

  1. We imported a security group into our CDK stack by using thefromSecurityGroupId static method on the SecurityGroup class

  2. The fromSecurityGroupId method takes the following parameters:

  • scope - the scope the method is invoked in

  • id - the construct identifier (must be unique in the scope)

  • securityGroupId - the id of the security group

  • securityGroupImportOptions - a configuration object for the importedsecurity group

    The allowAllOutbound property is set to true by default and specifies thatthe security group allows all outbound traffic. The fromSecurityGroupIdmethod assumes that the imported security group allows all outbound traffic,so it doesn't modify any of the egress rules. If we wanted to modify theoutbound rules of the imported security group, we would have to setallowAllOutbound to false.

    The mutable property is also set to true by default. Setting theproperty to true allows us to add rules to the imported security group. Wecan only add inbound rules unless allowAllOutbound is set to false.

Adding Inbound rules to an Imported Security Group in CDK #

In order to add an inbound rule to an imported security group in CDK, we haveto:

  1. Set the mutable property to true when importing the security group. Themutable prop is set to true by default, so we can omit passing italtogether
  2. Use theaddIngressRulemethod on the imported security group

The code for this article is available on GitHub

lib/cdk-starter-stack.ts

Copied!

import * as ec2 from 'aws-cdk-lib/aws-ec2';import * as cdk from 'aws-cdk-lib';export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ... rest // 👇 `mutable` is `true`, so we can add ingress rules importedSecurityGroup.addIngressRule( ec2.Peer.anyIpv4(), ec2.Port.tcp(22), 'allow SSH access from anywhere', ); }}
(Video) AWS re:Invent 2022 - Governance and security with infrastructure as code (DOP314)

We used the addIngressRule method to add the following inbound rule to theimported security group:

TypeProtocolPortSource
SSHTCP220.0.0.0/0

If I run the npx aws-cdk deploy command with an existing security group id, wecan see that the inbound rule gets applied:

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (7)

Note that if we were to destroy the CDK stack, the inbound rule would getdeleted and removed from the security group.

Adding Outbound rules to an Imported Security Group in CDK #

In order to add an outbound rule to an imported security group in CDK, we haveto:

  1. Set the allowAllOutbound property to false and the mutable property totrue

lib/cdk-starter-stack.ts

Copied!

const importedSecurityGroup = ec2.SecurityGroup.fromSecurityGroupId( this, 'imported-security-group', 'sg-0364cc5f9a979e9a6', {allowAllOutbound: false, mutable: true},);
  1. Use theaddEgressRulemethod on the imported security group

The code for this article is available on GitHub

Let's look at an example, where we add an egress rule to an imported securitygroup:

lib/cdk-starter-stack.ts

Copied!

import * as ec2 from 'aws-cdk-lib/aws-ec2';import * as cdk from 'aws-cdk-lib';export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); // ... rest // 👇 `mutable` is `true`, so we can add ingress rules importedSecurityGroup.addEgressRule( ec2.Peer.ipv4('10.0.0.0/16'), ec2.Port.tcp(3306), 'allow outgoing traffic on port 3306', ); }}

We used the addEgressRule method on the imported security group to add thefollowing outbound rule:

TypeProtocolPortDestination
MYSQLTCP330610.0.0.0/16

If I deploy the new egress rule, we can see that the outbound rules of theimported security group get updated:

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (8)

If we take a look at the resources the CloudFormation stack has provisioned, wecan see the ingress and egress security group rules:

Security Group Examples in AWS CDK - Complete Guide | bobbyhadz (9)

Deleting the stack would remove all of the ingress and egress rules we addedto the imported security group.

Videos

1. AWS re:Invent 2021 - Citi: Scaling security guardrail development via AWS CDK
(AWS Events)
2. Multiple environment setup in AWS CDK
(Mohammad Faisal)
3. AWS CDK(Cloud Development Kit) Tutorial
(JOMO Developer)
4. Tutorial: Launch an EC2 Instance With AWS CDK
(DJ STACKTRACE)
5. How to Create a Custom VPC with AWS CDK | AWS Cloud Development Kit (AWS CDK)?
(CLOUD LEARN HUB)
6. Define Cloud Infrastructure in Code with the AWS CDK
(Amazon Web Services)
Top Articles
Latest Posts
Article information

Author: Jerrold Considine

Last Updated: 02/03/2023

Views: 5811

Rating: 4.8 / 5 (58 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Jerrold Considine

Birthday: 1993-11-03

Address: Suite 447 3463 Marybelle Circles, New Marlin, AL 20765

Phone: +5816749283868

Job: Sales Executive

Hobby: Air sports, Sand art, Electronics, LARPing, Baseball, Book restoration, Puzzles

Introduction: My name is Jerrold Considine, I am a combative, cheerful, encouraging, happy, enthusiastic, funny, kind person who loves writing and wants to share my knowledge and understanding with you.