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))
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)),
})
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.
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))
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:
It works... Good luck!
Top comments (0)