AWS CDK で VPC Lambda の IPv6 アドレスへのアウトバウンド通信の許可が簡単に設定可能になりました

AWS CDK で VPC Lambda の IPv6 アドレスへのアウトバウンド通信の許可が簡単に設定可能になりました

Clock Icon2024.09.11

こんにちは、製造ビジネステクノロジー部の若槻です。

AWS CDK の最新のリリースで、下記のアップデートが追加されていました。

https://github.com/aws/aws-cdk/releases/tag/v2.157.0

lambda: added new property allowAllIpv6Outbound to FunctionOptions (#31013) (fa55194), closes #30994

Amazon VPC がアタッチされた Lambda 関数(しばしば VPC Lambda と呼ばれる)は VPC 内のリソースにアクセスできるようになります。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-vpc.html

今回の AWS CDK のアップデートは、VPC Lambda の IPv6 アドレスへのアウトバウンド通信の許可が aws_lambda モジュールで簡単に設定可能になったというものです。具体的には aws_lambda.Function クラスに追加された allowAllIpv6Outbound というプロパティを設定するだけで、IPv6 アドレスへのアウトバウンド通信を許可するかどうかを指定できるようになりました。

試してみた

allowAllIpv6Outbound を設定しない場合

まず、比較のために allowAllIpv6Outbound プロパティを設定しない場合の挙動を確認してみます。

CDK コード

次のように VPC Lambda を作成します。オプションは最低限のものとしています。

lib/cdk-sample-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';

export class CdkSampleStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const vpc = new ec2.Vpc(this, 'Vpc');

    new lambda.Function(this, 'MyFunction', {
      code: new lambda.InlineCode('def main(event, context): pass'),
      handler: 'index.main',
      runtime: lambda.Runtime.PYTHON_3_9,
      vpc,
    });
  }
}

デプロイ結果の確認

前述の CDK コードをデプロイし、作成された Lambda 関数をダッシュボードから確認してみます。

VPC で「すべての IPv4 アドレスへのみ」のアウトバウンド通信が許可されています。

CDK パッケージのアップデート

AWS CDK モジュールを v2.157.0 以上にアップデートします。

npm i aws-cdk-lib@latest aws-cdk@latest

IPv4 および IPv6 のアウトバウンド通信を許可する

アップデートにより利用可能になった allowAllIpv6Outbound プロパティを設定して、IPv4 および IPv6 のアウトバウンド通信を許可するようにしてみます。

CDK コード

既定値は false である allowAllIpv6Outbound プロパティを trueに設定します。これだけで IPv6 アドレスへのアウトバウンド通信が許可されます。

lib/cdk-sample-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';

export class CdkSampleStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const vpc = new ec2.Vpc(this, 'Vpc');

    new lambda.Function(this, 'MyFunction', {
      code: new lambda.InlineCode('def main(event, context): pass'),
      handler: 'index.main',
      runtime: lambda.Runtime.PYTHON_3_9,
      vpc,
      allowAllIpv6Outbound: true, // 追記
    });
  }
}

CDK Diff

前項でデプロイした CDK スタックとの差分を確認すると、IPv6 へのアウトバウンド通信が許可されるルールが Egress のセキュリティグループに追加されていることがわかります。

$ npx cdk diff
Stack CdkSampleStack
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
Security Group Changes
┌───┬─────────────────────────────────────┬─────┬────────────┬─────────────────┐
│   │ Group                               │ Dir │ Protocol   │ Peer            │
├───┼─────────────────────────────────────┼─────┼────────────┼─────────────────┤
│ + │ ${MyFunction/SecurityGroup.GroupId} │ Out │ Everything │ Everyone (IPv6) │
└───┴─────────────────────────────────────┴─────┴────────────┴─────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Resources
[~] AWS::EC2::SecurityGroup MyFunction/SecurityGroup MyFunctionSecurityGroup5241BB0E
 └─ [~] SecurityGroupEgress
     └─ @@ -3,5 +3,10 @@
        [ ]     "CidrIp": "0.0.0.0/0",
        [ ]     "Description": "Allow all outbound traffic by default",
        [ ]     "IpProtocol": "-1"
        [+]   },
        [+]   {
        [+]     "CidrIpv6": "::/0",
        [+]     "Description": "Allow all outbound ipv6 traffic by default",
        [+]     "IpProtocol": "-1"
        [ ]   }
        [ ] ]

✨  Number of stacks with differences: 1

デプロイ結果の確認

前述の CDK コードをデプロイし、Lambda 関数をダッシュボードから確認してみます。

VPC で「すべての IPv4 および IPv6 アドレス」へのアウトバウンド通信が許可されていますね。

IPv6 のアウトバウンド通信のみを許可する

先ほどは IPv4 および IPv6 の両方のアウトバウンド通信を許可しましたが、今度は IPv6 のアウトバウンド通信のみを許可する設定も簡単に行えます。

CDK コード

その場合は allowAllOutbound プロパティを false に設定します。このプロパティの既定値は true となります。

lib/cdk-sample-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';

export class CdkSampleStack extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const vpc = new ec2.Vpc(this, 'Vpc');

    new lambda.Function(this, 'MyFunction', {
      code: new lambda.InlineCode('def main(event, context): pass'),
      handler: 'index.main',
      runtime: lambda.Runtime.PYTHON_3_9,
      vpc,
      allowAllIpv6Outbound: true,
      allowAllOutbound: false, // 追記
    });
  }
}

CDK Diff

前項でデプロイした CDK スタックとの差分を確認すると、Egress のセキュリティグループで、すべての IPv4 アドレスへのアウトバウンド通信の許可が削除され、代わりに(!?) ICMP 通信が許可されるようになりました。

$ npx cdk diff
Stack CdkSampleStack
Hold on while we create a read-only change set to get a diff with accurate replacement information (use --no-change-set to use a less accurate but faster template-only diff)
Security Group Changes
┌───┬─────────────────────────────────────┬─────┬─────────────┬────────────────────┐
│   │ Group                               │ Dir │ Protocol    │ Peer               │
├───┼─────────────────────────────────────┼─────┼─────────────┼────────────────────┤
│ - │ ${MyFunction/SecurityGroup.GroupId} │ Out │ Everything  │ Everyone (IPv4)    │
├───┼─────────────────────────────────────┼─────┼─────────────┼────────────────────┤
│ + │ ${MyFunction/SecurityGroup.GroupId} │ Out │ ICMP 252-86 │ 255.255.255.255/32 │
└───┴─────────────────────────────────────┴─────┴─────────────┴────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)

Resources
[~] AWS::EC2::SecurityGroup MyFunction/SecurityGroup MyFunctionSecurityGroup5241BB0E
 └─ [~] SecurityGroupEgress
     └─ @@ -1,8 +1,10 @@
        [ ] [
        [ ]   {
        [-]     "CidrIp": "0.0.0.0/0",
        [-]     "Description": "Allow all outbound traffic by default",
        [-]     "IpProtocol": "-1"
        [+]     "CidrIp": "255.255.255.255/32",
        [+]     "Description": "Disallow all traffic",
        [+]     "FromPort": 252,
        [+]     "IpProtocol": "icmp",
        [+]     "ToPort": 86
        [ ]   },
        [ ]   {
        [ ]     "CidrIpv6": "::/0",

✨  Number of stacks with differences: 1

デプロイ結果の確認

前述の CDK コードをデプロイし、Lambda 関数をダッシュボードから確認してみます。

すべての「IPv6 アドレス」へのアウトバウンド通信が許可されていますね。

IPv4 を無効にすると ICMP が許可される意図は分かりかねますが、IP 通信ができないセキュリティグループが少なくとも基本的なネットワーク診断機能(例えば、ping コマンド)を持つようにするためなのでしょうか。

ICMP 通信の許可ルールが追加されるのは、すべてのアウトバウンド通信を許可するルールがデフォルトで追加されないようにするための措置とのことです。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-securitygroup.html#aws-resource-ec2-securitygroup--examples--Remove_the_default_rule:~:text=0/0-,Remove the default rule,-When you specify
https://github.com/aws/aws-cdk/blob/4d128330b058bf92c405661f6a2cb29fccaf6b38/packages/aws-cdk-lib/aws-ec2/lib/security-group.ts#L707-L715

おわりに

AWS CDK で VPC Lambda の IPv6 アドレスへのアウトバウンド通信の許可が簡単に設定可能になったのでご紹介しました。

セキュリティグループに明示的にルールを追加することなくプロパティを一つ設定するだけで、IPv6 アドレスへのアウトバウンド通信を許可できるのは便利ですね。

AWS サービス含め IPv6 をサポートするサービスは増えてきています。Lambda 関数が効率の良いネットワーク通信を行えるように、IPv6 対応を検討してみるのも良いかもしれません。

参考

https://dev.classmethod.jp/articles/vpc-lambda-ipv6-outbound/

以上

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.