CDK Expressモードで VPC Lambda の CreateNetworkInterface 権限エラーに遭遇した話

CDK Expressモードで VPC Lambda の CreateNetworkInterface 権限エラーに遭遇した話

CDK で Lambda を VPC 化したら CreateNetworkInterface の権限エラーが出ました。CDK は必要な権限を自動付与するはずなのになぜ起きるのか、検証で原因を切り分けていきます。
2026.07.21

はじめに

こんにちは、じゅんきちです。

AWS CDK でLambdaに関する以下のエラーに遭遇しました。

The provided execution role does not have permissions to
call CreateNetworkInterface on EC2 (Lambda, 400)

VPC Lambda は ENI(Elastic Network Interface)を作成するため、実行ロールに ec2:CreateNetworkInterface などの権限が必要です。しかし CDK は lambda.Functionvpc を指定すると AWSLambdaVPCAccessExecutionRole(ENI 権限を含むマネージドポリシー)を実行ロールへ自動付与するため、本来この権限エラーは起きないはずです。

結論

Express モードで実行していたことが原因でした。Express はポリシー伝播(eventual consistency)を待たずにロール更新を即完了扱いにするため、その直後に走る ENI 作成で CreateNetworkInterface が AccessDenied になります。

解決策は standard モードで行う(安定化=伝播待ちを飛ばさない)ことです。

Expressモードとは

Express モードは、CloudFormationの機能でスタックの安定化(stabilization)や eventual consistency のチェックを省略してデプロイを高速化するモードです。CDKでも対応しており--express フラグで利用します。

参考: CloudFormation Express mode

CDKの実装を確認する

CDK 内部で VPCAccess を付与している箇所はここです(aws-cdk-lib/aws-lambda/lib/function.ts)。

if (props.vpc) {
  // Policy that will have ENI creation permissions
  managedPolicies.push(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaVPCAccessExecutionRole'));
}

当然ながらvpcの設定有無で権限を付与してそうです。権限が付与されていることはsynthをして得られたテンプレートからも確認できました。となるとこれはcdkの問題ではなくIAM データプレーンの eventual consistency(ロール/ポリシーのアタッチが実際に有効になるまでの伝播遅延)かなと考えられます。Issueにも似たような事象が報告されていました(aws-cdk#7998)。

検証

検証は以下で行いました。

  • aws-cdk-lib 2.261.0 / aws-cdk 2.1132.0 / Node.js 26.5.0
  • リージョン: ap-northeast-1

検証用に、VPC 化の有無を context フラグで切り替えられる CDK スタックを用意しました。Lambda 部分の抜粋は次の通りです。

// vpcMode='on' のときだけ VpcConfig を付与。
// vpc=off でデプロイ後に vpc=on へ UPDATE すると「非VPC → VPC 化」を再現できる。
const vpcProps =
  vpcMode === 'on'
    ? { vpc, vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED } }
    : {};
const fn = new lambda.Function(this, 'Fn', {
  runtime: lambda.Runtime.NODEJS_22_X,
  handler: 'index.handler',
  code: lambda.Code.fromInline("exports.handler = async () => ({ statusCode: 200, body: 'ok' });"),
  timeout: Duration.seconds(10),
  ...vpcProps,
});

Express モードで事象を再現する

同一構成(role 自動生成)で、非VPC Lambda を VPC 化する UPDATE を Express で実行しました。ユーザー事象と同一のエラーが再現しました。イベントの時系列は以下の通りです。

時刻 リソース イベント
16:02:23 AWS::IAM::Role UPDATE_COMPLETE —「completed using Express Mode. It may continue becoming available in the background」(VPCAccess 追加を伝播待ちせず完了扱い)
16:02:25 AWS::Lambda::Function UPDATE 開始
16:02:27 AWS::Lambda::Function UPDATE_FAILED: CreateNetworkInterface 権限なし(ロール完了のわずか4秒後、ポリシー未伝播)

非VPC → VPC 化の UPDATE では、「既存ロールへ VPCAccess を追加」と「関数へ VpcConfig を追加(=ENI 作成)」が同一更新の中で連続して走ります。Express はロール更新を伝播待ちせず即完了にするため、その数秒後の関数更新の ENI 作成が、まだ伝播していない VPCAccess に対して実行され AccessDenied になります。

standardモードでやってみる

構成はそのままに、デプロイモードだけを standard に変えて同じ UPDATE を実行しました。今度は成功します。時系列は以下の通りです。

時刻 リソース イベント
16:15:34 AWS::IAM::Role UPDATE 開始
16:15:50 AWS::IAM::Role UPDATE_COMPLETE(安定化=伝播待ちに約16秒)
16:15:52 AWS::Lambda::Function UPDATE 開始
16:17:57 AWS::Lambda::Function UPDATE_COMPLETE(ENI 作成成功、約2分)

Express と standard で決定的に違うのは、ロール更新の完了までにかかる時間です。Express はロール更新を約1秒で完了扱いにし、その4秒後に走った ENI 作成が未伝播のポリシーに衝突しました。一方 standard はロール更新の安定化(伝播)に約16秒かけて待つため、その後の ENI 作成では権限が通ります。

補足:更新ではなく作成は通る

補足として、まっさらな状態からの CREATE(最初から VPC Lambda)は Express でも成功します。

AWS::Lambda::Function の作成は Express でも短絡されず、約2分かかるためです。この約2分の間にロールの VPCAccess が十分に伝播するので、ENI 作成時には権限が通ります。実際destroy→create を5回繰り返しても、CREATE では一度も再現しませんでした。

検証結果まとめ

まとめると次の通りです。

構成 結果
standard / fresh CREATE(VPC Lambda) ✅ 成功(Function 作成の約2分で伝播を吸収)
Express / fresh CREATE(VPC Lambda) ✅ 成功(Express でも Lambda::Function だけは約2分待機が残る)
standard / UPDATE 非VPC→VPC ✅ 成功(ロール更新に約16秒=伝播待ち)
Express / UPDATE 非VPC→VPC ❌ CreateNetworkInterface エラー再現

まとめ

  • Expressモードで非VPC Lambda を VPC Lambdaへ更新すると IAMが伝播する前に、CreateNetworkInterface が実行され権限エラーが出る。
  • 対策は standard モードでデプロイをするか、一度Lambdaを削除した後にVPC Lambdaとして再作成すること

どなたかの参考になれば幸いです。

この記事をシェアする

関連記事