AWS Lambda 从 VPC 内访问 Secrets Manager

AWS Lambda access Secrets Manager from within VPC

我有一个 lambda 需要与私有 VPC 中的 EC2 实例通信 'locally'。 API 密钥存储在 Secrets Manager 中。

使用 Secrets Manager 提供的默认代码和必要的 IAM 角色,我能够在我的 Lambda 中读取来自 Secrets Manager 的 API 密钥:

# Use this code snippet in your app.
# If you need more information about configurations or implementing the sample code, visit the AWS docs:   
# https://aws.amazon.com/developers/getting-started/python/

import boto3
import base64
from botocore.exceptions import ClientError

def get_secret():

    secret_name = "MYSECRET"
    region_name = "ap-southeast-2"

    # Create a Secrets Manager client
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )

    # In this sample we only handle the specific exceptions for the 'GetSecretValue' API.
    # See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
    # We rethrow the exception by default.

    try:
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
        )
    except ClientError as e:
 ... # Default error handling..
    else:
        # Decrypts secret using the associated KMS CMK.
        # Depending on whether the secret is a string or binary, one of these fields will be populated.
        if 'SecretString' in get_secret_value_response:
            secret = get_secret_value_response['SecretString']
            return secret
        else:
            decoded_binary_secret = base64.b64decode(get_secret_value_response['SecretBinary'])
            return decoded_binary_secret
 
def lambda_handler(event, context):
    secrt = get_secret()

    return {
        'statusCode': 200,
        "headers": {
            'Access-Control-Allow-Origin': '*',
            'Content-Type': 'application/json'
        },
        'body': secrt 
    }             

此 Lambda 能够从 Secrets Manager 成功检索并打印 API 密钥。

为了与 EC2 实例通信,我有一个带有辅助层和一些简单测试代码的 Lambda:

import apihelper
import json

def lambda_handler(event, context):
  conn = apihelper.getConnection('API KEY')
  return {
    'statusCode': 200,
    "headers": {
      "Access-Control-Allow-Origin": "*"
    },
    'body': json.dumps(conn.listProducts())
  }

此 lambda 在 VPC 子网中,并具有与 EC2 实例通信所需的安全组规则。硬编码 API KEY 它成功地 returns 来自 EC2 实例的预期数据。

当我尝试组合它们以使 API 密钥不被硬编码时,Lambda 不再有效。没有错误消息只是超时。

我试过:

我想我已经将范围缩小到 VPC。在我将其放入 VPC 之前,第一个仅打印出秘密的 Lambda 可以完美运行。但我不知道在哪里查看或如何配置它以允许 Lambda 与 VPC 内的 EC2 以及 Secrets Manager 通信。

There is no error message it just times out.

不幸的是,VPC 中的 lambda 函数 没有互联网访问权限,也没有 public IP。来自 docs:

Connecting a function to a public subnet does not give it internet access or a public IP address.

因此,当您使用 boto3:

    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )

连接到 Secrets Manager 它超时,因为 boto3 无法从 VPC 连接到 Secrets Manager 管理器。

两种纠正方法

  1. 将您的函数放在 私有子网 中,并使用 NAT gateway/instance 和正确配置的路由表来提供互联网访问,因此, Secrets Manager

  2. 在私有子网中设置VPC interface endpoint for Secrets Manager。这样,您的 lambda 函数将能够使用端点连接到 Secrets Manager,而无需互联网。