Security groups in AWS CDK EC2 provide network-level security through stateful firewall rules that control inbound and outbound traffic for AWS resources.
The SecurityGroup class creates and manages security groups with ingress and egress rules:
class SecurityGroup extends Resource implements ISecurityGroup {
constructor(scope: Construct, id: string, props: SecurityGroupProps);
// Security group properties
readonly securityGroupName: string;
readonly securityGroupId: string;
readonly securityGroupVpcId: string;
readonly allowAllOutbound: boolean;
readonly connections: Connections;
// Static factory methods
static fromLookupById(scope: Construct, id: string, securityGroupId: string): SecurityGroup;
static fromLookupByName(scope: Construct, id: string, securityGroupName: string, vpc: IVpc): SecurityGroup;
static fromSecurityGroupId(scope: Construct, id: string, securityGroupId: string, options?: SecurityGroupImportOptions): ISecurityGroup;
// Rule management
addIngressRule(peer: IPeer, connection: Port, description?: string, remoteRule?: boolean): void;
addEgressRule(peer: IPeer, connection: Port, description?: string, remoteRule?: boolean): void;
}
interface SecurityGroupProps {
readonly vpc: IVpc;
readonly securityGroupName?: string;
readonly description?: string;
readonly allowAllOutbound?: boolean;
readonly disableInlineRules?: boolean;
}The ISecurityGroup interface defines the contract for security group-like objects:
interface ISecurityGroup extends IResource, IPeer {
readonly securityGroupId: string;
readonly allowAllOutbound: boolean;
readonly connections: Connections;
addIngressRule(peer: IPeer, connection: Port, description?: string, remoteRule?: boolean): void;
addEgressRule(peer: IPeer, connection: Port, description?: string, remoteRule?: boolean): void;
}
interface SecurityGroupImportOptions {
readonly allowAllOutbound?: boolean;
readonly mutable?: boolean;
}Peers define the source or destination for security group rules:
class Peer {
// IPv4 peers
static ipv4(cidrIp: string): IPeer;
static anyIpv4(): IPeer;
// IPv6 peers
static ipv6(cidrIp: string): IPeer;
static anyIpv6(): IPeer;
// Prefix list peers
static prefixList(prefixListId: string): IPeer;
// Security group peers
static securityGroupId(securityGroupId: string, sourceSecurityGroupOwnerId?: string): IPeer;
}
interface IPeer extends IConnectable {
readonly canInlineRule: boolean;
readonly uniqueId: string;
toIngressRuleConfig(): any;
toEgressRuleConfig(): any;
}Ports define the protocol and port ranges for security group rules:
class Port {
constructor(props: PortProps);
readonly canInlineRule: boolean;
// TCP ports
static tcp(port: number): Port;
static tcpRange(startPort: number, endPort: number): Port;
static allTcp(): Port;
// UDP ports
static udp(port: number): Port;
static udpRange(startPort: number, endPort: number): Port;
static allUdp(): Port;
// ICMP
static icmpTypeAndCode(type: number, code: number): Port;
static icmpType(type: number): Port;
static icmpPing(): Port;
static allIcmp(): Port;
// Other protocols
static esp(): Port;
static ah(): Port;
static allTraffic(): Port;
toRuleJson(): any;
toString(): string;
}
interface PortProps {
readonly protocol: Protocol;
readonly fromPort?: number;
readonly toPort?: number;
readonly stringRepresentation: string;
}
enum Protocol {
ALL = '-1',
ICMP = 'icmp',
TCP = 'tcp',
UDP = 'udp',
IPV6_ICMP = 'icmpv6',
// ... and many numbered protocols
}import * as ec2 from "@aws-cdk/aws-ec2";
const vpc = new ec2.Vpc(this, "MyVpc");
const webSecurityGroup = new ec2.SecurityGroup(this, "WebSecurityGroup", {
vpc,
description: "Security group for web servers",
allowAllOutbound: true
});
// Add HTTP access from anywhere
webSecurityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
"Allow HTTP traffic from anywhere"
);
// Add HTTPS access from anywhere
webSecurityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(443),
"Allow HTTPS traffic from anywhere"
);const dbSecurityGroup = new ec2.SecurityGroup(this, "DatabaseSecurityGroup", {
vpc,
description: "Security group for database servers",
allowAllOutbound: false // Explicitly deny all outbound traffic
});
// Allow MySQL access only from web security group
dbSecurityGroup.addIngressRule(
webSecurityGroup,
ec2.Port.tcp(3306),
"Allow MySQL access from web servers"
);
// Allow PostgreSQL access from application security group
const appSecurityGroup = new ec2.SecurityGroup(this, "AppSecurityGroup", {
vpc,
description: "Security group for application servers"
});
dbSecurityGroup.addIngressRule(
appSecurityGroup,
ec2.Port.tcp(5432),
"Allow PostgreSQL access from application servers"
);const bastionSecurityGroup = new ec2.SecurityGroup(this, "BastionSecurityGroup", {
vpc,
description: "Security group for bastion host"
});
// Allow SSH from specific IP ranges
bastionSecurityGroup.addIngressRule(
ec2.Peer.ipv4("203.0.113.0/24"),
ec2.Port.tcp(22),
"Allow SSH from office network"
);
bastionSecurityGroup.addIngressRule(
ec2.Peer.ipv4("198.51.100.0/24"),
ec2.Port.tcp(22),
"Allow SSH from VPN network"
);
const privateSecurityGroup = new ec2.SecurityGroup(this, "PrivateSecurityGroup", {
vpc,
description: "Security group for private instances"
});
// Allow SSH only from bastion
privateSecurityGroup.addIngressRule(
bastionSecurityGroup,
ec2.Port.tcp(22),
"Allow SSH from bastion host"
);const albSecurityGroup = new ec2.SecurityGroup(this, "ALBSecurityGroup", {
vpc,
description: "Security group for Application Load Balancer"
});
// Allow HTTP and HTTPS from anywhere
albSecurityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(80),
"Allow HTTP from internet"
);
albSecurityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(443),
"Allow HTTPS from internet"
);
const backendSecurityGroup = new ec2.SecurityGroup(this, "BackendSecurityGroup", {
vpc,
description: "Security group for backend instances"
});
// Allow traffic from ALB to backend on application port
backendSecurityGroup.addIngressRule(
albSecurityGroup,
ec2.Port.tcp(8080),
"Allow traffic from ALB"
);const customSecurityGroup = new ec2.SecurityGroup(this, "CustomSecurityGroup", {
vpc,
description: "Security group with custom port configurations"
});
// Custom port range
customSecurityGroup.addIngressRule(
ec2.Peer.ipv4("10.0.0.0/16"),
ec2.Port.tcpRange(8000, 8999),
"Allow custom port range from VPC"
);
// ICMP ping
customSecurityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.icmpPing(),
"Allow ping from anywhere"
);
// UDP port
customSecurityGroup.addIngressRule(
ec2.Peer.ipv4("192.168.1.0/24"),
ec2.Port.udp(53),
"Allow DNS queries from private network"
);
// All traffic from same security group
customSecurityGroup.addIngressRule(
customSecurityGroup,
ec2.Port.allTraffic(),
"Allow all traffic within security group"
);const ipv6SecurityGroup = new ec2.SecurityGroup(this, "IPv6SecurityGroup", {
vpc,
description: "Security group with IPv6 support"
});
// Allow HTTP from any IPv6 address
ipv6SecurityGroup.addIngressRule(
ec2.Peer.anyIpv6(),
ec2.Port.tcp(80),
"Allow HTTP from any IPv6"
);
// Allow specific IPv6 CIDR
ipv6SecurityGroup.addIngressRule(
ec2.Peer.ipv6("2001:db8::/32"),
ec2.Port.tcp(443),
"Allow HTTPS from specific IPv6 network"
);// Import existing security group
const existingSecurityGroup = ec2.SecurityGroup.fromSecurityGroupId(
this,
"ExistingSecurityGroup",
"sg-12345678",
{
allowAllOutbound: false,
mutable: true
}
);
// Use imported security group in rules
const newSecurityGroup = new ec2.SecurityGroup(this, "NewSecurityGroup", {
vpc,
description: "New security group"
});
newSecurityGroup.addIngressRule(
existingSecurityGroup,
ec2.Port.tcp(3306),
"Allow database access from existing security group"
);const crossAccountSecurityGroup = ec2.Peer.securityGroupId(
"sg-87654321",
"123456789012" // Source account ID
);
const securityGroup = new ec2.SecurityGroup(this, "CrossAccountSG", {
vpc,
description: "Security group allowing cross-account access"
});
securityGroup.addIngressRule(
crossAccountSecurityGroup,
ec2.Port.tcp(443),
"Allow HTTPS from cross-account security group"
);const restrictedSecurityGroup = new ec2.SecurityGroup(this, "RestrictedSecurityGroup", {
vpc,
description: "Security group with restricted outbound access",
allowAllOutbound: false // Start with no outbound rules
});
// Allow HTTPS to specific destinations
restrictedSecurityGroup.addEgressRule(
ec2.Peer.ipv4("0.0.0.0/0"),
ec2.Port.tcp(443),
"Allow HTTPS outbound"
);
// Allow DNS queries
restrictedSecurityGroup.addEgressRule(
ec2.Peer.ipv4("0.0.0.0/0"),
ec2.Port.udp(53),
"Allow DNS queries"
);
// Allow outbound to database security group
restrictedSecurityGroup.addEgressRule(
dbSecurityGroup,
ec2.Port.tcp(5432),
"Allow outbound to database"
);const prefixListSecurityGroup = new ec2.SecurityGroup(this, "PrefixListSecurityGroup", {
vpc,
description: "Security group using prefix lists"
});
// Allow access from S3 prefix list
prefixListSecurityGroup.addIngressRule(
ec2.Peer.prefixList("pl-12345678"),
ec2.Port.tcp(443),
"Allow HTTPS from S3 prefix list"
);const ports = [80, 443, 8080, 8443];
const securityGroup = new ec2.SecurityGroup(this, "MultiPortSecurityGroup", {
vpc,
description: "Security group with multiple ports"
});
ports.forEach((port, index) => {
securityGroup.addIngressRule(
ec2.Peer.anyIpv4(),
ec2.Port.tcp(port),
`Allow traffic on port ${port}`
);
});