diff --git a/docs/guides/functions.md b/docs/guides/functions.md index 5de87f64a3..ac53b740a7 100644 --- a/docs/guides/functions.md +++ b/docs/guides/functions.md @@ -529,6 +529,51 @@ The Lambda function execution role must have permissions to create, describe and By default, when a Lambda function is executed inside a VPC, it loses internet access and some resources inside AWS may become unavailable. In order for S3 resources and DynamoDB resources to be available for your Lambda function running inside the VPC, a VPC end point needs to be created. For more information please check [VPC Endpoint for Amazon S3](https://aws.amazon.com/blogs/aws/new-vpc-endpoint-for-amazon-s3/). In order for other services such as Kinesis streams to be made available, a NAT Gateway needs to be configured inside the subnets that are being used to run the Lambda, for the VPC used to execute the Lambda. For more information, please check [Enable Outgoing Internet Access within VPC](https://medium.com/@philippholly/aws-lambda-enable-outgoing-internet-access-within-vpc-8dd250e11e12) +**VPC Lambda Internet IPv6 Access** + +Alternatively to setting up a NAT Gateway, you can also use an [egress-only internet gateway](https://docs.aws.amazon.com/vpc/latest/userguide/egress-only-internet-gateway.html) and allow your functions in a VPC to access the internet or other AWS services via IPv6. This eliminates the need for a NAT Gateway, reducing costs and simplifying architecture. In this case, VPC-configured Lambda functions can be allowed to access the internet using egress-only internet gateway by adding a `ipv6AllowedForDualStack` option to either the functions VPC specification: + +```yml +# serverless.yml +service: service-name +provider: aws + +functions: + hello: + handler: handler.hello + vpc: + ipv6AllowedForDualStack: true + securityGroupIds: + - securityGroupId1 + - securityGroupId2 + subnetIds: + - subnetId1 + - subnetId2 +``` + +Or if you want to apply VPC configuration to all functions in your service, you can add the configuration to the higher level `provider` object, and overwrite these service level config at the function level. For example: + +```yml +# serverless.yml +service: service-name +provider: + name: aws + vpc: + ipv6AllowedForDualStack: true + securityGroupIds: + - securityGroupId1 + - securityGroupId2 + subnetIds: + - subnetId1 + - subnetId2 + +functions: + ... +``` + +For more information, please check [Announcing AWS Lambda’s support for Internet Protocol Version 6 (IPv6) for outbound connections in VPC](https://aws.amazon.com/about-aws/whats-new/2023/10/aws-lambda-ipv6-outbound-connections-vpc/) + + ## Environment Variables You can add environment variable configuration to a specific function in `serverless.yml` by adding an `environment` object property in the function configuration. This object should contain a key-value pairs of string to string: diff --git a/docs/guides/serverless.yml.md b/docs/guides/serverless.yml.md index 20f7d144f1..e89c6d3ef6 100644 --- a/docs/guides/serverless.yml.md +++ b/docs/guides/serverless.yml.md @@ -490,8 +490,9 @@ Configure the Lambda functions to run inside a VPC ([complete documentation](./f ```yml provider: # Optional VPC settings - # If you use VPC then both securityGroupIds and subnetIds are required + # If you use VPC then both securityGroupIds and subnetIds are required, ipv6AllowedForDualStack is optional vpc: + ipv6AllowedForDualStack: true securityGroupIds: - securityGroupId1 - securityGroupId2 @@ -647,6 +648,7 @@ functions: # If you use VPC then both subproperties (securityGroupIds and subnetIds) are required # Can be set to '~' to disable the use of a VPC vpc: + ipv6AllowedForDualStack: true securityGroupIds: - securityGroupId1 - securityGroupId2 diff --git a/lib/plugins/aws/deploy-function.js b/lib/plugins/aws/deploy-function.js index 3640e58680..5eb5c1a9f5 100644 --- a/lib/plugins/aws/deploy-function.js +++ b/lib/plugins/aws/deploy-function.js @@ -378,6 +378,10 @@ class AwsDeployFunction { const vpc = functionObj.vpc || providerObj.vpc; params.VpcConfig = {}; + if (vpc.ipv6AllowedForDualStack) { + params.VpcConfig.Ipv6AllowedForDualStack = vpc.ipv6AllowedForDualStack; + } + if (Array.isArray(vpc.securityGroupIds) && !vpc.securityGroupIds.some(_.isObject)) { params.VpcConfig.SecurityGroupIds = vpc.securityGroupIds; } @@ -387,8 +391,11 @@ class AwsDeployFunction { } const didVpcChange = () => { - const remoteConfigToCompare = { SecurityGroupIds: [], SubnetIds: [] }; + const remoteConfigToCompare = { Ipv6AllowedForDualStack: false, SecurityGroupIds: [], SubnetIds: [] }; if (remoteFunctionConfiguration.VpcConfig) { + remoteConfigToCompare.Ipv6AllowedForDualStack = new Set( + remoteFunctionConfiguration.VpcConfig.Ipv6AllowedForDualStack || false + ); remoteConfigToCompare.SecurityGroupIds = new Set( remoteFunctionConfiguration.VpcConfig.SecurityGroupIds || [] ); @@ -397,6 +404,7 @@ class AwsDeployFunction { ); } const localConfigToCompare = { + Ipv6AllowedForDualStack: new Set(params.VpcConfig.Ipv6AllowedForDualStack || false), SecurityGroupIds: new Set(params.VpcConfig.SecurityGroupIds || []), SubnetIds: new Set(params.VpcConfig.SubnetIds || []), }; diff --git a/lib/plugins/aws/package/compile/functions.js b/lib/plugins/aws/package/compile/functions.js index 93cbe699d3..33b9fc586f 100644 --- a/lib/plugins/aws/package/compile/functions.js +++ b/lib/plugins/aws/package/compile/functions.js @@ -389,6 +389,9 @@ class AwsCompileFunctions { if (!this.serverless.service.provider.vpc) this.serverless.service.provider.vpc = {}; functionResource.Properties.VpcConfig = { + Ipv6AllowedForDualStack: + functionObject.vpc.ipv6AllowedForDualStack || + this.serverless.service.provider.vpc.ipv6AllowedForDualStack, SecurityGroupIds: functionObject.vpc.securityGroupIds || this.serverless.service.provider.vpc.securityGroupIds, diff --git a/lib/plugins/aws/provider.js b/lib/plugins/aws/provider.js index d4edf52965..44fcbd3fd3 100644 --- a/lib/plugins/aws/provider.js +++ b/lib/plugins/aws/provider.js @@ -661,6 +661,7 @@ class AwsProvider { awsLambdaVpcConfig: { type: 'object', properties: { + ipv6AllowedForDualStack: { type: 'boolean' }, securityGroupIds: { anyOf: [ {