> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fjall.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Security Group

> Configure AWS security groups in Fjall to control inbound and outbound traffic with least-privilege ingress and egress rules.

## Overview

The Security Group resource is a virtual firewall for controlling inbound and outbound traffic to AWS resources.

<Note>
  This is a thin wrapper over the standard CDK `SecurityGroup`. The only Fjall
  addition is a default description (`${id} Security Group`) when you omit one.
  Every other property and method behaves exactly as the CDK construct.
</Note>

## Resource Class

```typescript theme={null}
import { SecurityGroup } from "@fjall/components-infrastructure/lib/resources/aws/networking/securityGroup";
```

## Basic Usage

```typescript theme={null}
const securityGroup = new SecurityGroup(this, "MySecurityGroup", {
  vpc: myVpc,
  description: "Security group for my application",
});
```

## Configuration Options

### Core Properties

| Property            | Type      | Description                | Default                |
| ------------------- | --------- | -------------------------- | ---------------------- |
| `vpc`               | `IVpc`    | VPC for the security group | Required               |
| `description`       | `string`  | Security group description | `${id} Security Group` |
| `securityGroupName` | `string`  | Security group name        | Auto-generated         |
| `allowAllOutbound`  | `boolean` | Allow all outbound traffic | `true`                 |

All standard CDK SecurityGroup properties are supported through the extending class.

## Default Behaviour

* **Description**: Automatically set to `${id} Security Group` if not provided
* **Outbound Rules**: All traffic allowed by default
* **Inbound Rules**: No inbound traffic allowed by default (deny all)

## Common Patterns

### Web Server Security Group

```typescript theme={null}
const webSg = new SecurityGroup(this, "WebServerSG", {
  vpc: vpc,
  description: "Security group for web servers",
});

// Allow HTTP from anywhere
webSg.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(80), "Allow HTTP");

// Allow HTTPS from anywhere
webSg.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443), "Allow HTTPS");
```

### Application Server Security Group

```typescript theme={null}
const appSg = new SecurityGroup(this, "AppServerSG", {
  vpc: vpc,
  description: "Security group for application servers",
});

// Only allow traffic from web tier
appSg.addIngressRule(webSg, ec2.Port.tcp(8080), "Allow from web tier");
```

### Database Security Group

```typescript theme={null}
const dbSg = new SecurityGroup(this, "DatabaseSG", {
  vpc: vpc,
  description: "Security group for database",
  allowAllOutbound: false, // Restrict outbound for databases
});

// Only allow from app tier
dbSg.addIngressRule(appSg, ec2.Port.tcp(5432), "PostgreSQL from app tier");
```

## Working with Connections

### Using Connections Interface

```typescript theme={null}
const sg = new SecurityGroup(this, "ServiceSG", {
  vpc: vpc,
});

// Allow another resource to connect
const database = new RdsInstance(this, "Database", { vpc });

sg.connections.allowTo(database, ec2.Port.tcp(5432), "Allow database access");

// Allow from another resource
sg.connections.allowFrom(loadBalancer, ec2.Port.tcp(8080), "Allow from ALB");
```

### Bi-directional Connections

```typescript theme={null}
const sg1 = new SecurityGroup(this, "Service1", { vpc });
const sg2 = new SecurityGroup(this, "Service2", { vpc });

// Allow bidirectional communication
sg1.connections.allowTo(sg2, ec2.Port.tcp(8080));
sg2.connections.allowTo(sg1, ec2.Port.tcp(9090));
```

## Advanced Rules

### IP-based Rules

```typescript theme={null}
const sg = new SecurityGroup(this, "RestrictedSG", {
  vpc: vpc,
});

// Office IP range
sg.addIngressRule(
  ec2.Peer.ipv4("203.0.113.0/24"),
  ec2.Port.tcp(22),
  "SSH from office",
);

// Multiple CIDR blocks
["10.0.0.0/8", "172.16.0.0/12"].forEach((cidr) => {
  sg.addIngressRule(
    ec2.Peer.ipv4(cidr),
    ec2.Port.allTraffic(),
    `Allow from ${cidr}`,
  );
});
```

### Port Ranges

```typescript theme={null}
const sg = new SecurityGroup(this, "RangesSG", {
  vpc: vpc,
});

// TCP port range
sg.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcpRange(8000, 8999),
  "Application ports",
);

// Custom protocol
sg.addIngressRule(
  ec2.Peer.anyIpv4(),
  new ec2.Port({
    protocol: ec2.Protocol.UDP,
    fromPort: 500,
    toPort: 500,
  }),
  "IPSec",
);
```

### Prefix Lists

```typescript theme={null}
const sg = new SecurityGroup(this, "PrefixListSG", {
  vpc: vpc,
});

// AWS service prefix lists
sg.addIngressRule(
  ec2.Peer.prefixList("pl-12345678"), // S3 prefix list
  ec2.Port.tcp(443),
  "HTTPS from S3",
);
```

## Security Group Chaining

### Three-Tier Architecture

```typescript theme={null}
// Public tier
const publicSg = new SecurityGroup(this, "PublicSG", {
  vpc: vpc,
  description: "Public-facing load balancer",
});

publicSg.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(443),
  "HTTPS from internet",
);

// App tier
const appSg = new SecurityGroup(this, "AppSG", {
  vpc: vpc,
  description: "Application servers",
});

appSg.addIngressRule(publicSg, ec2.Port.tcp(8080), "From load balancer");

// Data tier
const dataSg = new SecurityGroup(this, "DataSG", {
  vpc: vpc,
  description: "Database servers",
});

dataSg.addIngressRule(appSg, ec2.Port.tcp(5432), "From application tier");
```

## Egress Rules

### Restrict Outbound Traffic

```typescript theme={null}
const restrictedSg = new SecurityGroup(this, "RestrictedSG", {
  vpc: vpc,
  allowAllOutbound: false, // No default outbound rules
});

// Only allow HTTPS outbound
restrictedSg.addEgressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(443), "HTTPS only");

// Allow DNS
restrictedSg.addEgressRule(ec2.Peer.anyIpv4(), ec2.Port.udp(53), "DNS queries");
```

### Service-Specific Egress

```typescript theme={null}
const sg = new SecurityGroup(this, "ServiceSG", {
  vpc: vpc,
  allowAllOutbound: false,
});

// S3 access via VPC endpoint
sg.addEgressRule(ec2.Peer.prefixList("pl-s3"), ec2.Port.tcp(443), "S3 access");

// RDS access
sg.addEgressRule(dbSg, ec2.Port.tcp(5432), "Database access");
```

## Integration Examples

### With ECS

```typescript theme={null}
const clusterSg = new SecurityGroup(this, "ClusterSG", {
  vpc: vpc,
  description: "ECS cluster security group",
});

const service = new ecs.FargateService(this, "Service", {
  cluster: cluster,
  taskDefinition: taskDef,
  securityGroups: [clusterSg],
});

// Allow from ALB
clusterSg.connections.allowFrom(alb, ec2.Port.tcp(containerPort));
```

### With Lambda

```typescript theme={null}
const lambdaSg = new SecurityGroup(this, "LambdaSG", {
  vpc: vpc,
  description: "Lambda function security group",
});

const fn = new lambda.Function(this, "Function", {
  vpc: vpc,
  securityGroups: [lambdaSg],
  // ... other props
});

// Allow Lambda to access RDS
lambdaSg.connections.allowTo(database, ec2.Port.tcp(5432));
```

### With RDS

```typescript theme={null}
const dbSg = new SecurityGroup(this, "DatabaseSG", {
  vpc: vpc,
  description: "RDS security group",
});

const database = new rds.DatabaseInstance(this, "Database", {
  vpc: vpc,
  securityGroups: [dbSg],
  // ... other props
});

// Application access
appSg.connections.allowTo(database, ec2.Port.tcp(5432));
```

## Best Practices

### Least Privilege

```typescript theme={null}
// Bad - Too permissive
sg.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.allTraffic(),
  "Allow all", // Never do this!
);

// Good - Specific rules
sg.addIngressRule(
  ec2.Peer.ipv4("10.0.0.0/16"),
  ec2.Port.tcp(443),
  "HTTPS from VPC only",
);
```

### Rule Documentation

```typescript theme={null}
// Always add meaningful descriptions
sg.addIngressRule(
  webTierSg,
  ec2.Port.tcp(8080),
  "HTTP traffic from web tier ALB for health checks",
);
```

### Avoid Circular Dependencies

```typescript theme={null}
// Can cause circular dependency
const sg1 = new SecurityGroup(this, "SG1", { vpc });
const sg2 = new SecurityGroup(this, "SG2", { vpc });

sg1.addIngressRule(sg2, ec2.Port.tcp(80), "From SG2");
sg2.addIngressRule(sg1, ec2.Port.tcp(80), "From SG1");

// Better approach - use connections
sg1.connections.allowFrom(sg2, ec2.Port.tcp(80));
sg2.connections.allowFrom(sg1, ec2.Port.tcp(80));
```

## Monitoring and Compliance

### VPC Flow Logs

```typescript theme={null}
// Enable flow logs to monitor security group traffic
vpc.addFlowLog("SecurityGroupFlowLog", {
  destination: ec2.FlowLogDestination.toCloudWatchLogs(),
  trafficType: ec2.FlowLogTrafficType.REJECT,
});
```

### AWS Config Rules

```typescript theme={null}
new config.CfnConfigRule(this, "SGComplianceRule", {
  source: {
    sourceIdentifier: "INCOMING_SSH_DISABLED",
  },
  scope: {
    complianceResourceTypes: ["AWS::EC2::SecurityGroup"],
  },
});
```

## Complete Example

```typescript theme={null}
import { SecurityGroup } from "@fjall/components-infrastructure/lib/resources/aws/networking/securityGroup";
import * as ec2 from "aws-cdk-lib/aws-ec2";

// Create VPC
const vpc = new ec2.Vpc(this, "AppVpc", {
  maxAzs: 2,
});

// Bastion host security group
const bastionSg = new SecurityGroup(this, "BastionSG", {
  vpc: vpc,
  description: "Bastion host security group",
});

bastionSg.addIngressRule(
  ec2.Peer.ipv4("203.0.113.0/24"), // Office IP
  ec2.Port.tcp(22),
  "SSH from office",
);

// Web tier security group
const webSg = new SecurityGroup(this, "WebSG", {
  vpc: vpc,
  description: "Web application security group",
});

webSg.addIngressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(443),
  "HTTPS from internet",
);

webSg.addIngressRule(bastionSg, ec2.Port.tcp(22), "SSH from bastion");

// App tier security group
const appSg = new SecurityGroup(this, "AppSG", {
  vpc: vpc,
  description: "Application tier security group",
  allowAllOutbound: false,
});

appSg.addIngressRule(webSg, ec2.Port.tcp(8080), "HTTP from web tier");

appSg.addIngressRule(
  bastionSg,
  ec2.Port.tcp(22),
  "SSH from bastion for debugging",
);

// Restrict outbound
appSg.addEgressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(443),
  "HTTPS for external APIs",
);

appSg.addEgressRule(
  ec2.Peer.anyIpv4(),
  ec2.Port.tcp(80),
  "HTTP for package downloads",
);

// Database security group
const dbSg = new SecurityGroup(this, "DatabaseSG", {
  vpc: vpc,
  description: "Database security group",
  allowAllOutbound: false, // Databases shouldn't initiate connections
});

dbSg.addIngressRule(appSg, ec2.Port.tcp(5432), "PostgreSQL from app tier");

dbSg.addIngressRule(
  bastionSg,
  ec2.Port.tcp(5432),
  "PostgreSQL from bastion for maintenance",
);

// Export security group IDs
new CfnOutput(this, "WebSecurityGroupId", {
  value: webSg.securityGroupId,
  description: "Web tier security group ID",
});
```

## Troubleshooting

### Common Issues

1. **Connection timeouts**: Check both ingress and egress rules
2. **Circular dependencies**: Use connections interface
3. **Rule limits**: Maximum 60 inbound and 60 outbound rules
4. **ICMP traffic**: Remember to allow for ping/traceroute

### Debug Commands

```bash theme={null}
# List security groups
aws ec2 describe-security-groups --group-ids sg-12345

# Check rules
aws ec2 describe-security-group-rules \
  --filters "Name=security-group-id,Values=sg-12345"

# Test connectivity
aws ec2 describe-vpc-peering-connections
```

## Next Steps

<CardGroup cols={2}>
  <Card title="VPC" icon="network-wired" href="/resources/networking/vpc">
    Define the network the security group attaches to
  </Card>

  <Card title="ECS Cluster" icon="server" href="/resources/compute/ecs-cluster">
    Attach security groups to container services
  </Card>

  <Card title="RDS Instance" icon="database" href="/resources/database/rds-instance">
    Restrict database access by tier
  </Card>

  <Card title="Lambda Function" icon="bolt" href="/resources/compute/lambda-function">
    Place functions inside a secured VPC
  </Card>
</CardGroup>
