Create and Configure Security Groups

The aws:ec2/securityGroup:SecurityGroup resource, part of the Pulumi AWS provider, provisions the security group container itself: its name, VPC placement, and metadata. This guide focuses on four capabilities: creating security groups with companion rule resources, inline rule definitions, prefix list references, and rule removal patterns.

Security groups don’t define access control in isolation. They exist within VPCs and depend on companion SecurityGroupIngressRule and SecurityGroupEgressRule resources for rule definitions. Current best practice avoids inline ingress and egress blocks due to limitations with multiple CIDR blocks and rule metadata. The examples are intentionally small and show individual configuration patterns. Combine them with your own VPC infrastructure and access requirements.

Create a security group with separate rule resources

Most deployments define security groups as containers, then attach individual rules using companion resources. This avoids conflicts when managing multiple CIDR blocks.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const allowTls = new aws.ec2.SecurityGroup("allow_tls", {
    name: "allow_tls",
    description: "Allow TLS inbound traffic and all outbound traffic",
    vpcId: main.id,
    tags: {
        Name: "allow_tls",
    },
});
const allowTlsIpv4 = new aws.vpc.SecurityGroupIngressRule("allow_tls_ipv4", {
    securityGroupId: allowTls.id,
    cidrIpv4: main.cidrBlock,
    fromPort: 443,
    ipProtocol: "tcp",
    toPort: 443,
});
const allowTlsIpv6 = new aws.vpc.SecurityGroupIngressRule("allow_tls_ipv6", {
    securityGroupId: allowTls.id,
    cidrIpv6: main.ipv6CidrBlock,
    fromPort: 443,
    ipProtocol: "tcp",
    toPort: 443,
});
const allowAllTrafficIpv4 = new aws.vpc.SecurityGroupEgressRule("allow_all_traffic_ipv4", {
    securityGroupId: allowTls.id,
    cidrIpv4: "0.0.0.0/0",
    ipProtocol: "-1",
});
const allowAllTrafficIpv6 = new aws.vpc.SecurityGroupEgressRule("allow_all_traffic_ipv6", {
    securityGroupId: allowTls.id,
    cidrIpv6: "::/0",
    ipProtocol: "-1",
});
import pulumi
import pulumi_aws as aws

allow_tls = aws.ec2.SecurityGroup("allow_tls",
    name="allow_tls",
    description="Allow TLS inbound traffic and all outbound traffic",
    vpc_id=main["id"],
    tags={
        "Name": "allow_tls",
    })
allow_tls_ipv4 = aws.vpc.SecurityGroupIngressRule("allow_tls_ipv4",
    security_group_id=allow_tls.id,
    cidr_ipv4=main["cidrBlock"],
    from_port=443,
    ip_protocol="tcp",
    to_port=443)
allow_tls_ipv6 = aws.vpc.SecurityGroupIngressRule("allow_tls_ipv6",
    security_group_id=allow_tls.id,
    cidr_ipv6=main["ipv6CidrBlock"],
    from_port=443,
    ip_protocol="tcp",
    to_port=443)
allow_all_traffic_ipv4 = aws.vpc.SecurityGroupEgressRule("allow_all_traffic_ipv4",
    security_group_id=allow_tls.id,
    cidr_ipv4="0.0.0.0/0",
    ip_protocol="-1")
allow_all_traffic_ipv6 = aws.vpc.SecurityGroupEgressRule("allow_all_traffic_ipv6",
    security_group_id=allow_tls.id,
    cidr_ipv6="::/0",
    ip_protocol="-1")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/vpc"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		allowTls, err := ec2.NewSecurityGroup(ctx, "allow_tls", &ec2.SecurityGroupArgs{
			Name:        pulumi.String("allow_tls"),
			Description: pulumi.String("Allow TLS inbound traffic and all outbound traffic"),
			VpcId:       pulumi.Any(main.Id),
			Tags: pulumi.StringMap{
				"Name": pulumi.String("allow_tls"),
			},
		})
		if err != nil {
			return err
		}
		_, err = vpc.NewSecurityGroupIngressRule(ctx, "allow_tls_ipv4", &vpc.SecurityGroupIngressRuleArgs{
			SecurityGroupId: allowTls.ID(),
			CidrIpv4:        pulumi.Any(main.CidrBlock),
			FromPort:        pulumi.Int(443),
			IpProtocol:      pulumi.String("tcp"),
			ToPort:          pulumi.Int(443),
		})
		if err != nil {
			return err
		}
		_, err = vpc.NewSecurityGroupIngressRule(ctx, "allow_tls_ipv6", &vpc.SecurityGroupIngressRuleArgs{
			SecurityGroupId: allowTls.ID(),
			CidrIpv6:        pulumi.Any(main.Ipv6CidrBlock),
			FromPort:        pulumi.Int(443),
			IpProtocol:      pulumi.String("tcp"),
			ToPort:          pulumi.Int(443),
		})
		if err != nil {
			return err
		}
		_, err = vpc.NewSecurityGroupEgressRule(ctx, "allow_all_traffic_ipv4", &vpc.SecurityGroupEgressRuleArgs{
			SecurityGroupId: allowTls.ID(),
			CidrIpv4:        pulumi.String("0.0.0.0/0"),
			IpProtocol:      pulumi.String("-1"),
		})
		if err != nil {
			return err
		}
		_, err = vpc.NewSecurityGroupEgressRule(ctx, "allow_all_traffic_ipv6", &vpc.SecurityGroupEgressRuleArgs{
			SecurityGroupId: allowTls.ID(),
			CidrIpv6:        pulumi.String("::/0"),
			IpProtocol:      pulumi.String("-1"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var allowTls = new Aws.Ec2.SecurityGroup("allow_tls", new()
    {
        Name = "allow_tls",
        Description = "Allow TLS inbound traffic and all outbound traffic",
        VpcId = main.Id,
        Tags = 
        {
            { "Name", "allow_tls" },
        },
    });

    var allowTlsIpv4 = new Aws.Vpc.SecurityGroupIngressRule("allow_tls_ipv4", new()
    {
        SecurityGroupId = allowTls.Id,
        CidrIpv4 = main.CidrBlock,
        FromPort = 443,
        IpProtocol = "tcp",
        ToPort = 443,
    });

    var allowTlsIpv6 = new Aws.Vpc.SecurityGroupIngressRule("allow_tls_ipv6", new()
    {
        SecurityGroupId = allowTls.Id,
        CidrIpv6 = main.Ipv6CidrBlock,
        FromPort = 443,
        IpProtocol = "tcp",
        ToPort = 443,
    });

    var allowAllTrafficIpv4 = new Aws.Vpc.SecurityGroupEgressRule("allow_all_traffic_ipv4", new()
    {
        SecurityGroupId = allowTls.Id,
        CidrIpv4 = "0.0.0.0/0",
        IpProtocol = "-1",
    });

    var allowAllTrafficIpv6 = new Aws.Vpc.SecurityGroupEgressRule("allow_all_traffic_ipv6", new()
    {
        SecurityGroupId = allowTls.Id,
        CidrIpv6 = "::/0",
        IpProtocol = "-1",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.SecurityGroup;
import com.pulumi.aws.ec2.SecurityGroupArgs;
import com.pulumi.aws.vpc.SecurityGroupIngressRule;
import com.pulumi.aws.vpc.SecurityGroupIngressRuleArgs;
import com.pulumi.aws.vpc.SecurityGroupEgressRule;
import com.pulumi.aws.vpc.SecurityGroupEgressRuleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var allowTls = new SecurityGroup("allowTls", SecurityGroupArgs.builder()
            .name("allow_tls")
            .description("Allow TLS inbound traffic and all outbound traffic")
            .vpcId(main.id())
            .tags(Map.of("Name", "allow_tls"))
            .build());

        var allowTlsIpv4 = new SecurityGroupIngressRule("allowTlsIpv4", SecurityGroupIngressRuleArgs.builder()
            .securityGroupId(allowTls.id())
            .cidrIpv4(main.cidrBlock())
            .fromPort(443)
            .ipProtocol("tcp")
            .toPort(443)
            .build());

        var allowTlsIpv6 = new SecurityGroupIngressRule("allowTlsIpv6", SecurityGroupIngressRuleArgs.builder()
            .securityGroupId(allowTls.id())
            .cidrIpv6(main.ipv6CidrBlock())
            .fromPort(443)
            .ipProtocol("tcp")
            .toPort(443)
            .build());

        var allowAllTrafficIpv4 = new SecurityGroupEgressRule("allowAllTrafficIpv4", SecurityGroupEgressRuleArgs.builder()
            .securityGroupId(allowTls.id())
            .cidrIpv4("0.0.0.0/0")
            .ipProtocol("-1")
            .build());

        var allowAllTrafficIpv6 = new SecurityGroupEgressRule("allowAllTrafficIpv6", SecurityGroupEgressRuleArgs.builder()
            .securityGroupId(allowTls.id())
            .cidrIpv6("::/0")
            .ipProtocol("-1")
            .build());

    }
}
resources:
  allowTls:
    type: aws:ec2:SecurityGroup
    name: allow_tls
    properties:
      name: allow_tls
      description: Allow TLS inbound traffic and all outbound traffic
      vpcId: ${main.id}
      tags:
        Name: allow_tls
  allowTlsIpv4:
    type: aws:vpc:SecurityGroupIngressRule
    name: allow_tls_ipv4
    properties:
      securityGroupId: ${allowTls.id}
      cidrIpv4: ${main.cidrBlock}
      fromPort: 443
      ipProtocol: tcp
      toPort: 443
  allowTlsIpv6:
    type: aws:vpc:SecurityGroupIngressRule
    name: allow_tls_ipv6
    properties:
      securityGroupId: ${allowTls.id}
      cidrIpv6: ${main.ipv6CidrBlock}
      fromPort: 443
      ipProtocol: tcp
      toPort: 443
  allowAllTrafficIpv4:
    type: aws:vpc:SecurityGroupEgressRule
    name: allow_all_traffic_ipv4
    properties:
      securityGroupId: ${allowTls.id}
      cidrIpv4: 0.0.0.0/0
      ipProtocol: '-1'
  allowAllTrafficIpv6:
    type: aws:vpc:SecurityGroupEgressRule
    name: allow_all_traffic_ipv6
    properties:
      securityGroupId: ${allowTls.id}
      cidrIpv6: ::/0
      ipProtocol: '-1'

The SecurityGroup resource creates the container with a name and vpcId. Companion SecurityGroupIngressRule and SecurityGroupEgressRule resources attach to it via securityGroupId. This approach provides unique IDs for each rule, enabling tags and descriptions per rule.

Allow all outbound traffic using inline rules

AWS creates an allow-all egress rule by default for new VPC security groups. Pulumi removes this default, requiring explicit recreation.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.ec2.SecurityGroup("example", {egress: [{
    fromPort: 0,
    toPort: 0,
    protocol: "-1",
    cidrBlocks: ["0.0.0.0/0"],
    ipv6CidrBlocks: ["::/0"],
}]});
import pulumi
import pulumi_aws as aws

example = aws.ec2.SecurityGroup("example", egress=[{
    "from_port": 0,
    "to_port": 0,
    "protocol": "-1",
    "cidr_blocks": ["0.0.0.0/0"],
    "ipv6_cidr_blocks": ["::/0"],
}])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := ec2.NewSecurityGroup(ctx, "example", &ec2.SecurityGroupArgs{
			Egress: ec2.SecurityGroupEgressArray{
				&ec2.SecurityGroupEgressArgs{
					FromPort: pulumi.Int(0),
					ToPort:   pulumi.Int(0),
					Protocol: pulumi.String("-1"),
					CidrBlocks: pulumi.StringArray{
						pulumi.String("0.0.0.0/0"),
					},
					Ipv6CidrBlocks: pulumi.StringArray{
						pulumi.String("::/0"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Ec2.SecurityGroup("example", new()
    {
        Egress = new[]
        {
            new Aws.Ec2.Inputs.SecurityGroupEgressArgs
            {
                FromPort = 0,
                ToPort = 0,
                Protocol = "-1",
                CidrBlocks = new[]
                {
                    "0.0.0.0/0",
                },
                Ipv6CidrBlocks = new[]
                {
                    "::/0",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.SecurityGroup;
import com.pulumi.aws.ec2.SecurityGroupArgs;
import com.pulumi.aws.ec2.inputs.SecurityGroupEgressArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new SecurityGroup("example", SecurityGroupArgs.builder()
            .egress(SecurityGroupEgressArgs.builder()
                .fromPort(0)
                .toPort(0)
                .protocol("-1")
                .cidrBlocks("0.0.0.0/0")
                .ipv6CidrBlocks("::/0")
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:ec2:SecurityGroup
    properties:
      egress:
        - fromPort: 0
          toPort: 0
          protocol: '-1'
          cidrBlocks:
            - 0.0.0.0/0
          ipv6CidrBlocks:
            - ::/0

The egress block uses protocol “-1” to represent all protocols. The cidrBlocks and ipv6CidrBlocks arrays allow traffic to all IPv4 and IPv6 destinations. Setting fromPort and toPort to 0 with protocol “-1” allows all port ranges.

Reference AWS-managed prefix lists in rules

AWS services publish prefix lists representing IP ranges for services like S3 or CloudFront. VPC endpoints expose prefix list IDs that can be referenced in rules.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const myEndpoint = new aws.ec2.VpcEndpoint("my_endpoint", {});
const example = new aws.ec2.SecurityGroup("example", {egress: [{
    fromPort: 0,
    toPort: 0,
    protocol: "-1",
    prefixListIds: [myEndpoint.prefixListId],
}]});
import pulumi
import pulumi_aws as aws

my_endpoint = aws.ec2.VpcEndpoint("my_endpoint")
example = aws.ec2.SecurityGroup("example", egress=[{
    "from_port": 0,
    "to_port": 0,
    "protocol": "-1",
    "prefix_list_ids": [my_endpoint.prefix_list_id],
}])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		myEndpoint, err := ec2.NewVpcEndpoint(ctx, "my_endpoint", nil)
		if err != nil {
			return err
		}
		_, err = ec2.NewSecurityGroup(ctx, "example", &ec2.SecurityGroupArgs{
			Egress: ec2.SecurityGroupEgressArray{
				&ec2.SecurityGroupEgressArgs{
					FromPort: pulumi.Int(0),
					ToPort:   pulumi.Int(0),
					Protocol: pulumi.String("-1"),
					PrefixListIds: pulumi.StringArray{
						myEndpoint.PrefixListId,
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var myEndpoint = new Aws.Ec2.VpcEndpoint("my_endpoint");

    var example = new Aws.Ec2.SecurityGroup("example", new()
    {
        Egress = new[]
        {
            new Aws.Ec2.Inputs.SecurityGroupEgressArgs
            {
                FromPort = 0,
                ToPort = 0,
                Protocol = "-1",
                PrefixListIds = new[]
                {
                    myEndpoint.PrefixListId,
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.VpcEndpoint;
import com.pulumi.aws.ec2.SecurityGroup;
import com.pulumi.aws.ec2.SecurityGroupArgs;
import com.pulumi.aws.ec2.inputs.SecurityGroupEgressArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var myEndpoint = new VpcEndpoint("myEndpoint");

        var example = new SecurityGroup("example", SecurityGroupArgs.builder()
            .egress(SecurityGroupEgressArgs.builder()
                .fromPort(0)
                .toPort(0)
                .protocol("-1")
                .prefixListIds(myEndpoint.prefixListId())
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:ec2:SecurityGroup
    properties:
      egress:
        - fromPort: 0
          toPort: 0
          protocol: '-1'
          prefixListIds:
            - ${myEndpoint.prefixListId}
  myEndpoint:
    type: aws:ec2:VpcEndpoint
    name: my_endpoint

The prefixListIds property accepts a list of managed prefix list IDs. Here, a VPC endpoint’s prefixListId provides the AWS service ranges. This avoids hardcoding IP ranges that AWS manages and updates.

Remove all rules from an existing security group

The ingress and egress properties are processed in attributes-as-blocks mode. Removing them from configuration won’t destroy managed rules; set them to empty arrays explicitly.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.ec2.SecurityGroup("example", {
    name: "sg",
    vpcId: exampleAwsVpc.id,
    ingress: [],
    egress: [],
});
import pulumi
import pulumi_aws as aws

example = aws.ec2.SecurityGroup("example",
    name="sg",
    vpc_id=example_aws_vpc["id"],
    ingress=[],
    egress=[])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := ec2.NewSecurityGroup(ctx, "example", &ec2.SecurityGroupArgs{
			Name:    pulumi.String("sg"),
			VpcId:   pulumi.Any(exampleAwsVpc.Id),
			Ingress: ec2.SecurityGroupIngressArray{},
			Egress:  ec2.SecurityGroupEgressArray{},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Ec2.SecurityGroup("example", new()
    {
        Name = "sg",
        VpcId = exampleAwsVpc.Id,
        Ingress = new[] {},
        Egress = new[] {},
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.SecurityGroup;
import com.pulumi.aws.ec2.SecurityGroupArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new SecurityGroup("example", SecurityGroupArgs.builder()
            .name("sg")
            .vpcId(exampleAwsVpc.id())
            .ingress()
            .egress()
            .build());

    }
}
resources:
  example:
    type: aws:ec2:SecurityGroup
    properties:
      name: sg
      vpcId: ${exampleAwsVpc.id}
      ingress: []
      egress: []

Setting ingress and egress to empty arrays ([]) removes all managed rules while preserving the security group. This is necessary because the attributes-as-blocks processing mode doesn’t treat property removal as destruction.

Beyond These Examples

These snippets focus on specific security group features: security group creation with companion rule resources, inline rule definitions for egress, prefix list references for AWS services, and rule removal patterns. They’re intentionally minimal rather than full network security configurations.

The examples may reference pre-existing infrastructure such as VPCs with subnets, and VPC endpoints for prefix list examples. They focus on security group configuration rather than provisioning the underlying network.

To keep things focused, common security group patterns are omitted, including:

  • Ingress rules for specific protocols (SSH, HTTP, HTTPS)
  • Self-referencing security group rules
  • Cross-security-group references
  • IPv6-only rules
  • Description and tags for individual rules
  • Rule priority and conflict resolution

These omissions are intentional: the goal is to illustrate how each security group feature is wired, not provide drop-in security modules. See the Security Group resource reference for all available configuration options.

Frequently Asked Questions

Rule Management & Best Practices
Why shouldn't I use inline ingress and egress rules?
The ingress and egress arguments struggle with managing multiple CIDR blocks and lack unique IDs, tags, and descriptions. Use aws.vpc.SecurityGroupIngressRule and aws.vpc.SecurityGroupEgressRule resources instead, with one CIDR block per rule.
What happens if I mix inline rules with separate rule resources?
Mixing ingress/egress arguments with aws.vpc.SecurityGroupIngressRule, aws.vpc.SecurityGroupEgressRule, or aws.ec2.SecurityGroupRule resources causes rule conflicts, perpetual differences, and overwritten rules. Choose one approach and stick with it.
How do I remove all ingress and egress rules from a security group?
You must explicitly set ingress: [] and egress: [] in your configuration. Simply removing these arguments won’t destroy the managed rules due to attributes-as-blocks mode.
Deletion & Lifecycle Issues
Why is my Lambda-associated security group taking 45 minutes to delete?
Security groups associated with Lambda Functions can take up to 45 minutes to delete due to improved VPC networking changes. The provider waits at least 45 minutes even if you specify a shorter delete timeout.
What properties force a new security group to be created?
Changing name, description, namePrefix, or vpcId forces recreation since these properties are immutable. This can cause the Security Group Deletion Problem if the group is attached to other resources.
How do I handle cyclic dependencies that prevent security group deletion?
Set revokeRulesOnDelete to true to revoke all attached ingress and egress rules before deletion. This is useful when AWS services like Elastic Map Reduce automatically add rules with cyclic dependencies.
Egress & Default Behavior
What happened to the default 'allow all' egress rule?
AWS creates a default ‘ALLOW ALL’ egress rule when creating a security group in a VPC, but the provider removes this default. You must explicitly recreate it if you want to allow all outbound traffic.
How do I allow all outbound traffic from my security group?
Create an egress rule with cidrIpv4: '0.0.0.0/0' (or cidrIpv6: '::/0' for IPv6) and ipProtocol: '-1', as shown in the egress examples.
What happens if I don't specify cidrBlocks or ipv6CidrBlocks in a rule?
If you don’t specify cidrBlocks or ipv6CidrBlocks in ingress or egress blocks, traffic will be blocked by default.
Advanced Configuration
How do I use prefix lists with security group rules?
Use the prefixListIds argument in egress or ingress blocks. Prefix list IDs are exported on VPC Endpoints, or you can find them using the aws.ec2.getPrefixList data source.
Can I use tags to classify my security group instead of the description?
Yes, you should use tags for classification that needs updating. The description property is immutable and maps to AWS GroupDescription, which has no Update API.
Are there restrictions on referencing security groups across VPC peering?
Yes, there are certain restrictions when referencing security groups across VPC peering connections. Refer to the VPC Peering User Guide for details.

Ready to get started?

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Create free account