DEV Community

Cover image for AWS CDK and security group configuration (Golang)
Oleg Sydorov
Oleg Sydorov

Posted on

AWS CDK and security group configuration (Golang)

It's obvious that all cloud software is primarily network software. Therefore, when working with software deployment in the AWS environment, including AWS Lambda, we deal with security groups. If we do not explicitly define and configure a security group in the CDK code, one will be implicitly created, for example, when creating an ALB or AWS API Gateway. Such a security group, created implicitly by the CDK tool, will be configured as "any to any," which is often unacceptable in a production environment. Staying within the concept of CICD, the solution is to explicitly configure the security group in the code.

Let's consider this action with specific examples.

Assume we have a VPC that is either created or imported. We will explicitly create a security group:

sg := awsec2.NewSecurityGroup(stack, jsii.String("MyAwsLambdaSG"), &awsec2.SecurityGroupProps{
        Vpc:               vpc,
        AllowAllOutbound:  jsii.Bool(false),
        SecurityGroupName: jsii.String("MyAwsLambdaSG"),
    })

// Allow incoming HTTPS to ALB
sg.AddIngressRule(awsec2.Peer_AnyIpv4(), awsec2.Port_Tcp(jsii.Number(443)), jsii.String("Allow HTTPS traffic"), jsii.Bool(false))

// Allow outbound needed traffic
sg.AddEgressRule(awsec2.Peer_Ipv4(jsii.String("x.x.x.x/x")), awsec2.Port_AllTcp(), jsii.String("Allow outbound TCP traffic"), jsii.Bool(false))
Enter fullscreen mode Exit fullscreen mode

Next, add the created security group to the Lambda configuration:

lambdaFunction := awscdklambdagoalpha.NewGoFunction(stack, jsii.String("MyAWSLambda"), &awscdklambdagoalpha.GoFunctionProps{
        Runtime:                      awslambda.Runtime_PROVIDED_AL2(),
        Entry:                        jsii.String("./src"),
        Architecture:                 awslambda.Architecture_ARM_64(),
        ReservedConcurrentExecutions: jsii.Number(10),
        Bundling: &awscdklambdagoalpha.BundlingOptions{
            GoBuildFlags: jsii.Strings(`-ldflags "-s -w" -mod=vendor`),
        },
        Environment:          nil,
        FunctionName:         jsii.String("MyAWSLambda"),
        Description:          jsii.String("MyAWSLambda backend Lambda function"),
        Role:                 applicationRole,
        Vpc:                  vpc,
        SecurityGroups:       &[]awsec2.ISecurityGroup{sg}, // NB!
        MemorySize:           jsii.Number(128),
        EphemeralStorageSize: awscdk.Size_Mebibytes(jsii.Number(512)),
    })
Enter fullscreen mode Exit fullscreen mode

Important!

The permissions set in a security group work within the context of the given Lambda and do not affect the configuration of the ALB, endpoints, or API Gateway. For instance, ANY to TCP 443 does not mean any HTTPS access from outside if the access point is configured as PRIVATE, etc. This is a separate area of responsibility and configuration.

Some difficulties may arise when configuring with cloud resources like AWS DynamoDB. To ensure access to such resources, it is convenient to use the Prefix List ID. Follow the instructions to find the ID.

Find Managed prefix lists category

Search by resource type

Preview the details

The console can be used as well:
aws ec2 describe-managed-prefix-lists --query "PrefixLists[?PrefixListName=='com.amazonaws.<region>.dynamodb'].PrefixListId"

Next, let's move on to the code.

Let's configure the endpoint to access dynamoDB:

vpc.AddGatewayEndpoint(jsii.String("DynamoDbEndpoint"), &awsec2.GatewayVpcEndpointOptions{
        Service: awsec2.GatewayVpcEndpointAwsService_DYNAMODB(),
        Subnets: &[]*awsec2.SubnetSelection{
            {SubnetType: awsec2.SubnetType_PRIVATE_WITH_EGRESS},
        },
    })

sg := awsec2.NewSecurityGroup(stack, jsii.String("MyAWSLambdaSG"), &awsec2.SecurityGroupProps{
        Vpc:               vpc,
        AllowAllOutbound:  jsii.Bool(false),
        SecurityGroupName: jsii.String("MyAWSLambdaSG"),
    })

// Add a rule for dynamoDB

dynamoDbPrefixListID := "pl-12345xyz"
sg.AddEgressRule(awsec2.Peer_PrefixList(jsii.String(dynamoDbPrefixListID)), awsec2.Port_Tcp(jsii.Number(443)), jsii.String("Allow outbound dynamoDB"), jsii.Bool(false))
Enter fullscreen mode Exit fullscreen mode

Note that the rule 0.0.0.0/0 443 will also work, but this solution does not seem to be the best.

When finished, here is the result:

Inbound rule

Outbound rule

It works... Good luck!

Top comments (0)