Amazon Web Services ブログ

VPC設定にAWS Lambda IAM条件キーを使用する

本投稿は、Senior Developer Advocate, Julian Woodの寄稿によるものです。

AWS Identity and Access Management(IAM)条件キーを使用して、AWS Lambda 関数のAmazon Virtual Private Cloud(VPC)設定を制御できるようになりました 。 IAM条件キーを使用すると、IAMポリシーステートメントが適用される条件をさらに絞り込むことができます。関数を作成および更新する権限を付与するときに、IAMポリシーで新しい条件キーを使用できます。

VPC設定の3つの新しい条件キーは、lambda:VpcIds、lambda:SubnetIds、そして、 lambda:SecurityGroupIds です。キーにより、ユーザーが1つ以上の許可されたVPC、サブネット、およびセキュリティグループに接続された関数のみをデプロイできるようにすることができます。ユーザーが許可されていないVPC設定で関数を作成または更新しようとすると、Lambdaは操作を拒否します。

LambdaとVPCの関係を理解する

Lambdaの実行環境はすべて、Lambdaサービスが所有するVPC内で動作します。 Lambda関数は、Lambda API を呼び出すことによってのみ呼び出すことができます。関数が実行される実行環境への直接のネットワークアクセスはありません。

非VPC接続のLambda関数

Lambda関数がカスタマーアカウントのVPCに接続するように構成されていない場合、関数はパブリックインターネットで利用可能なすべてのリソースにアクセスできます。これには、他のAWSサービス、APIのHTTPSエンドポイント、またはAWS外のサービスとエンドポイントが含まれます。関数はVPC内のプライベートリソースに直接には接続できません。

VPC接続のLambda関数

Lambda関数を設定して、カスタマーアカウントのVPC内のプライベートサブネットに接続できます。 Lambda関数がカスタマーアカウントVPCに接続するように設定されている場合も、そのLambda関数は引き続きAWS LambdaサービスVPC内で実行されます。この場合、Lambda関数はすべてのネットワークトラフィックをカスタマーアカウント内VPC経由で送信し、このカスタマーVPCのネットワーク制御に従います。これらのコントロールを使用して、セキュリティグループネットワークACL を設定し関数が接続可能な範囲を制御できます。Lambda関数からの送信トラフィックは独自のネットワークアドレス空間から送信され、VPCフローログ を使用してネットワークを可視化できます。

パブリックインターネットを含むネットワークロケーションへのアクセスを制限できます。 カスタマーアカウント内のVPCに接続されたLambda関数は、デフォルトではインターネットにアクセスできません。関数にインターネットへのアクセスを許可するには、送信トラフィックをパブリックサブネットのネットワークアドレス変換(NAT)ゲートウェイ にルーティングできます。

Lambda関数を設定してカスタマーアカウント内のVPCに接続すると、AWS Hyperplane によって管理される共有Elastic Network Interface(ENI)が使用されます。この接続により、VPC-to-VPC NATが作成され、クロスアカウントに接続されます。これにより、Lambda関数からプライベートリソースへのネットワークアクセスが可能になります。

AWS Lambda サービスVPCからVPC-to-VPT NATを利用しカスタマーVPCへ

AWS Lambda サービスVPCからVPC-to-VPT NATを利用しカスタマーVPCへ

Hyperplane ENIは、Lambdaサービスが制御し、カスタマーアカウント内のVPCに存在するマネージドネットワークインターフェースリソースです。複数の実行環境がENIを共有して、カスタマーアカウントのVPC内のリソースに安全にアクセスします。カスタマー側からのLambda実行環境(LambdaサービスVPC内)への直接のネットワークアクセスは出来ないことにご注意ください。

ENIはいつ作られるのか?

Lambda関数が作成されるか、そのVPC設定が更新されると、ネットワークインターフェイスの作成が行われます。関数が呼び出されると、実行環境は事前に作成されたネットワークインターフェースを使用し、そのインターフェースへのネットワークトンネルをすばやく確立します。これにより、コールドスタート時のネットワークインターフェースの作成と接続に関連していたレイテンシが削減 されています。

どのくらいの数のENIが必要か?

ネットワークインターフェイスは実行環境全体で共有されるため、通常、関数ごとに必要なネットワークインターフェイスはほんの一握りです。アカウント内の関数全体で一意のセキュリティグループとサブネットのペアごとに、個別のネットワークインターフェイスが必要です。同じアカウントの複数の関数が同じセキュリティグループとサブネットのペアを使用する場合、同じネットワークインターフェイスを再利用します。このように、複数の関数を備えているが、ネットワークとセキュリティの構成が同じである単一のアプリケーションは、既存のインターフェース構成の恩恵を受けることができます。

関数のスケーリングは、ネットワークインターフェイスの数に直接関係しなくなりました。Hyperplane ENIは、大量のLambda関数の同時実行をサポートするようにスケールします。

関数が長期間Active状態でない場合、Lambdaサービスはネットワークインターフェイスを回収し、Lambda関数はアイドルになり、そしてInactive状態に推移します。アイドルな関数を呼び出して再びActive状態にする必要があります。最初の呼び出しは失敗し、ネットワークインターフェイスが使用可能になるまで、関数は再びPending状態に入ります。詳細については別ブログ、AWS Lambda関数の状態の追跡を参照ください。

VPC設定に新しいLambda条件キーを使用する

新しいVPC条件キー設定を使用すると、1つ以上の必要なVPC、サブネット、およびセキュリティグループを指定できます。 lambda:VpcIds値は、CreateFunction API 呼び出し元が提供するサブネットとセキュリティグループから推測されます。

条件の構文は次の形式です

"Condition":{"{condition-operator}":{"{condition-key}":"{condition-value}"}}

複数のキー と値を持つ条件演算子を使用して、ポリシードキュメントを作成できます。次の画像は4つのサブネットで構成されたプライベートVPCの例になります。

プライベートVPCサブネット

プライベートVPCサブネット

 

プライベートVPCでMySQLデータベースインスタンスを実行しています。インスタンスは、サブネットsubnet-046c0d0c487b0515bのus-east-1bで実行され、サブネットsubnet-091e180fa55fb8e83のus-east-1cへフェイルオーバーします。データベースへのアクセスを許可するために関連付されたセキュリティグループsg-0a56588b3406ee3d3があります。これはプライベートサブネットなので、インターネットアクセスは許可しません。

こちらのアカウントで作成したLambda関数は、このプライベートVPCに必ず接続しなければならないということを動作確認したいと思います。

 

  1. アカウントに適用するために、次のIAMポリシードキュメントを作成します。 ForAllValues:StringNotEquals条件演算子と共にDeny条件キーを使用して、必要なVpcIdを指定します。
    • {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Sid": "Stmt159186333251",
                  "Action": [
                      "lambda:CreateFunction",
                      "lambda:UpdateFunctionConfiguration"
                  ],
                  "Effect": "Deny",
                  "Resource": "*",
                  "Condition": {
                      "ForAllValues:StringNotEquals": {
                          "lambda:VpcIds": [
                              "vpc-0eebf3d0fe63a2db1"
                          ]
                      }
                  }
              }
          ]
      }
       
  2. API呼び出しコマンドから、–vpc-configを除外して、VPCに接続しないLambda関数を作成してみましょう。
    • aws lambda create-function --function-name MyVPCLambda1 \
      	--runtime python3.7 --handler helloworld.handler \
      	--zip-file fileb://vpccondition.zip \
      	--region us-east-1 --role arn:aws:iam::123456789012:role/VPCConditionLambdaRole
  3. 明示的な拒否を意味するAccessDeniedExceptionエラーを受け取ります。
    • Lambda関数の作成時のAccessDeniedExceptionLambda関数の作成時のAccessDeniedException
  4. Lambda関数を再度作成し、セキュリティグループとともにVPCにサブネットの1つを含めてみましょう。 –vpc-configにSubnetIdsとSecurityGroupIdの両方の値を含める必要があります。
    • aws lambda create-function --function-name MyVPCLambda1 \
      	--vpc-config "SubnetIds=['subnet-019c87c9b67742a8f'],SecurityGroupIds=['sg-0a56588b3406ee3d3']" \
      	--runtime python3.7 --handler helloworld.handler \
      	--zip-file fileb://vpccondition.zip \
      	--region us-east-1 --role arn:aws:iam::123456789012:role/VPCConditionLambdaRole
      
      

      こうすることでLambda関数を作成することができるようになります。

      VPCに接続されたLambda関数を正常に作成する

      VPCに接続されたLambda関数を正常に作成する

       

ここで、このアカウントで作成されたすべてのLambda関数の構成が次のようになっていることを確認します。

  • 上記のプライベートVPCに接続していること
  • 両方のサブネットがデータベースインスタンスを含むこと
  • MySQLデータベースインスタンスを含むセキュリティグループ

アカウントのIAMポリシードキュメントを修正して、SubnetIdsとSecurityGroupIdsの制限を含めます。 VpcIdsは自動で推測されるため、指定する必要はありません。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt159186333252",
            "Action": [
                "lambda:CreateFunction",
                "lambda:UpdateFunctionConfiguration"
            ],
            "Effect": "Deny",
            "Resource": "*",
            "Condition": {
                "ForAllValues:StringNotEquals": {
                    "lambda:SubnetIds": [
                        "subnet-046c0d0c487b0515b",
                        "subnet-091e180fa55fb8e83"
                    ]
                }
            }
        },
        {
            "Sid": "Stmt159186333253",
            "Action": [
                "lambda:CreateFunction",
                "lambda:UpdateFunctionConfiguration"
            ],
            "Effect": "Deny",
            "Resource": "*",
            "Condition": {
                "ForAllValues:StringNotEquals": {
                    "lambda:SecurityGroupIds": [
                        "sg-0a56588b3406ee3d3"
                    ]
                }
            }
        }
    ]
}

セキュリティグループとともに、許可された権限リストにないVPCのサブネットを–vpc-configの値として使用して、別のLambda関数を作成します。

aws lambda create-function --function-name MyVPCLambda2 \
  --vpc-config "SubnetIds=['subnet-019c87c9b67742a8f'],SecurityGroupIds=['sg-0a56588b3406ee3d3']" \
  --runtime python3.7 \
  --handler helloworld.handler \
  --zip-file fileb://vpccondition.zip \
  --region us-east-1 \
  --role arn:aws:iam::123456789012:role/VPCConditionLambdaRole

AccessDeniedExceptionエラーが表示されます。

ここで、有効で許可されたSubnetIdおよびSecurityGroupIdの両方を指定して、再試行します。

aws lambda create-function --function-name MyVPCLambda2 \
  --vpc-config "SubnetIds=['subnet-046c0d0c487b0515b','subnet-091e180fa55fb8e83'],SecurityGroupIds=['sg-0a56588b3406ee3d3']" \
  --runtime python3.7 \
  --handler helloworld.handler \
  --zip-file fileb://vpccondition.zip \
  --region us-east-1 \
  --role arn:aws:iam::123456789012:role/VPCConditionLambdaRole

これで、Lambda関数の作成が成功します。

特定のサブネットとセキュリティグループに接続されたLambda関数を正常に作成

特定のサブネットとセキュリティグループに接続されたLambda関数を正常に作成

これらの設定により、許可されたVPCネットワークセキュリティ設定でのみLambda関数を作成できることを確認できます。

Lambda関数の更新

Lambda関数の設定を更新するときに、VPC設定がすでに存在する場合は、再度指定する必要はありません。 Lambdaは、IAMへの認証呼び出しを行う前に、既存のVPC設定を確認します。

VPC設定を指定せずにLambda関数のメモリを増加させる次のコマンドは、VPC設定がすでに存在するため成功します。

aws lambda update-function-configuration \
    --function-name MyVPCLambda2 \
    --memory-size 512

 

Lambdaレイヤー条件キー

Lambdaには、別の既存の条件キーとして lambda:Layer もあります。
Lambdaレイヤーを使用すると、複数のLambda関数間、または複数のアプリケーション間でコードとコンテンツを共有できます。

lambda:Layer 条件キーを使用すると、特定のレイヤーまたは許可されたレイヤーのグループのみを関数に含めることを強制できます。レイヤーの使用を禁止することもできます。レイヤーの使用をアカウントのレイヤーのみに制限して、自分のものではないアカウントによって公開されたレイヤーの使用を防ぐこともできます。

まとめ

IAM条件キーを使用してLambda関数のVPC設定を制御できるようになりました。

新しいVPC設定条件キーは、Lambdaが利用可能なすべてのAWSリージョンで利用できます。新しい条件キーの詳細とポリシーの例を表示するには、Lambda開発者ガイドの「VPC 設定で IAM 条件キーを使用する」および「Lambdaアクションのリソースと条件」を参照してください。 IAM条件キーの使用の詳細については、IAMユーザーガイドの「IAM JSON ポリシーの要素:Condition」を参照してください。

翻訳はServerless Specialist Solutions Architect 下川 賢介(@_kensh) が担当しました。原文はこちらです。