#secrets-manager #secret #aws-lambda #agent

app aws_secretsmanager_agent

AWS Secrets Manager Agent 是一个本地 HTTP 服务,您可以在您的计算环境中安装并使用它来从 Secrets Manager 读取密钥并在内存中缓存

1 个稳定版本

1.0.0 2024年7月31日

101网络编程 中排名 #101

Download history 100/week @ 2024-07-26 31/week @ 2024-08-02 3/week @ 2024-08-09

134 每月下载量

Apache-2.0

170KB
3K SLoC

AWS Secrets Manager Agent

AWS Secrets Manager Agent 是一个客户端 HTTP 服务,您可以使用它来在不同的环境中(如 AWS Lambda、Amazon Elastic Container Service、Amazon Elastic Kubernetes Service 和 Amazon Elastic Compute Cloud)标准化从 Secrets Manager 消费密钥。Secrets Manager Agent 可以检索并缓存密钥,以便您的应用程序可以直接从缓存中消费密钥。这意味着您可以从本地主机获取应用程序所需的密钥,而不是调用 Secrets Manager。Secrets Manager Agent 只能向 Secrets Manager 发送读取请求 - 它不能修改密钥。

Secrets Manager Agent 使用您在环境中提供的 AWS 凭据调用 Secrets Manager。Secrets Manager Agent 提供防止服务器端请求伪造 (SSRF) 的保护,以帮助提高密钥的安全性。您可以通过设置最大连接数、生存时间 (TTL)、本地主机 HTTP 端口和缓存大小来配置 Secrets Manager Agent。

由于 Secrets Manager Agent 使用内存缓存,因此它会在 Secrets Manager Agent 重启时重置。Secrets Manager Agent 定期刷新缓存的密钥值。刷新发生在您尝试在 TTL 过期后从 Secrets Manager Agent 读取密钥时。默认刷新频率(TTL)为 300 秒,您可以通过使用 配置文件 来更改它,该文件您可以通过使用 --config 命令行参数传递给 Secrets Manager Agent。Secrets Manager Agent 不包括缓存失效。例如,如果密钥在缓存条目过期之前轮换,Secrets Manager Agent 可能会返回过时的密钥值。

Secrets Manager Agent 以与 GetSecretValue 响应相同的格式返回密钥值。密钥值在缓存中未加密。

要下载源代码,请参阅 GitHub 上的 https://github.com/aws/aws-secretsmanager-agent

主题

步骤 1: 构建 Secrets Manager 代理的二进制文件

要本地构建 Secrets Manager 代理的二进制文件,需要标准开发工具和 Rust 工具。或者,您可以为支持它的系统进行交叉编译,或者可以使用 Rust 交叉编译工具进行交叉编译。


[ 基于 RPM 的系统 ]

  1. 在 AL2023 等基于 RPM 的系统上,您可以使用开发工具组来安装开发工具。

    sudo yum -y groupinstall "Development Tools"
    
  2. 请参考 Rust 文档 中的 安装 Rust 指令。

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    . "$HOME/.cargo/env"
    
  3. 使用 cargo build 命令构建代理

    cargo build --release
    

    您将在以下位置找到可执行文件: target/release/aws-secrets-manager-agent


[ 基于 Debian 的系统 ]

  1. 在基于 Debian 的系统(如 Ubuntu)上,您可以使用 build-essential 软件包来安装开发者工具。

    sudo apt install build-essential
    
  2. 请参考 Rust 文档 中的 安装 Rust 指令。

    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    . "$HOME/.cargo/env"
    
  3. 使用 cargo build 命令构建代理

    cargo build --release
    

    您将在以下位置找到可执行文件: target/release/aws-secrets-manager-agent


[ Windows ]

要在 Windows 上构建,请参阅 Microsoft Windows 文档 中的 为 Rust 设置 Windows 开发环境 指令。


[ 本地交叉编译 ]

在提供 mingw-w64 软件包的发行版(如 Ubuntu)上,您可以进行本地交叉编译。

# Install the cross compile tool chain
sudo add-apt-repository universe
sudo apt install -y mingw-w64
    
# Install the rust build targets
rustup target add x86_64-pc-windows-gnu
    
# Cross compile the agent for Windows
cargo build --release --target x86_64-pc-windows-gnu

您将在以下位置找到可执行文件: target/x86_64-pc-windows-gnu/release/aws-secrets-manager-agent.exe


[ 使用 Rust 交叉编译工具进行交叉编译 ]

如果系统上没有提供本地交叉编译工具,您可以使用 Rust 交叉项目。更多信息请参阅 https://github.com/cross-rs/cross

重要
我们建议为构建环境预留 32GB 的磁盘空间。

# Install and start docker
sudo yum -y install docker
sudo systemctl start docker
sudo systemctl enable docker # Make docker start after reboot
    
# Give ourselves permission to run the docker images without sudo
sudo usermod -aG docker $USER
newgrp docker
    
# Install cross and cross compile the executable
cargo install cross
cross build --release --target x86_64-pc-windows-gnu

步骤 2: 安装 Secrets Manager 代理

根据计算类型,安装 Secrets Manager 代理有多种选项。


[ Amazon EC2 ]

要安装 Secrets Manager 代理

  1. 请使用仓库中提供的 install 脚本。

    脚本在启动时生成一个随机的 SSRF 令牌,并将其存储在 /var/run/awssmatoken 文件中。令牌可供 install 脚本创建的 awssmatokenreader 组读取。

  2. 要允许您的应用程序读取令牌文件,您需要将运行应用程序的用户账户添加到 awssmatokenreader 组。例如,您可以使用以下 usermod 命令授予应用程序读取令牌文件的权限,其中 <APP_USER> 是应用程序运行的用户 ID。

    sudo usermod -aG awssmatokenreader <APP_USER>
    

[ 以容器侧车运行 ]

您可以使用 Docker 将 Secrets Manager Agent 作为与应用程序并行的侧车容器运行。然后,您的应用程序可以检索 Secrets Manager Agent 提供的本地 HTTP 服务器上的密钥。有关 Docker 的信息,请参阅 Docker 文档

要使用 Docker 为 Secrets Manager Agent 创建侧车容器

  1. 为 Secrets Manager Agent 侧车容器创建一个 Dockerfile。以下示例创建了一个包含 Secrets Manager Agent 二进制文件的 Docker 容器。

    # Use the latest Debian image as the base
    FROM debian:latest
    
    # Set the working directory inside the container
    WORKDIR /app 
    
    # Copy the Secrets Manager Agent binary to the container
    COPY secrets-manager-agent . 
    
    # Install any necessary dependencies
    RUN apt-get update && apt-get install -y ca-certificates 
    
    # Set the entry point to run the Secrets Manager Agent binary
    ENTRYPOINT ["./secrets-manager-agent"]
    
  2. 为您的客户端应用程序创建一个 Dockerfile。

  3. 创建一个Docker Compose文件来运行两个容器,确保它们使用相同的网络接口。这是必要的,因为Secrets Manager Agent不接受来自localhost接口之外请求。以下示例显示了Docker Compose文件,其中network_mode键将secrets-manager-agent容器连接到client-application容器的网络命名空间,这使得它们可以共享相同的网络接口。重要
    您必须加载AWS凭证和应用程序的SSRF令牌,以便能够使用Secrets Manager Agent。请参阅以下内容
    管理访问在《亚马逊弹性Kubernetes服务用户指南》中亚马逊弹性容器服务任务IAM角色在《亚马逊弹性容器服务开发者指南》中

    version: '3'
    services:
        client-application:
        container_name: client-application
        build:
            context: .
            dockerfile: Dockerfile.client
        command: tail -f /dev/null  # Keep the container running
        
    
        secrets-manager-agent:
        container_name: secrets-manager-agent
        build:
            context: .
            dockerfile: Dockerfile.agent
        network_mode: "container:client-application"  # Attach to the client-application container's network
        depends_on:
            - client-application
    
  4. secrets-manager-agent二进制文件复制到包含您的Dockerfile和Docker Compose文件的同一目录。

  5. 使用以下https://docs.docker.net.cn/reference/cli/docker/compose/命令根据提供的Dockerfile构建和运行容器。

    docker-compose up --build
    
  6. 现在,您可以在客户端容器中使用Secrets Manager Agent检索机密。有关更多信息,请参阅第3步:使用Secrets Manager Agent检索机密


[ AWS Lambda ]

您可以将Secrets Manager Agent作为AWS Lambda扩展进行打包然后,您可以将它作为层添加到您的Lambda函数中,并从您的Lambda函数调用Secrets Manager Agent以获取机密。

以下说明显示了如何使用示例脚本secrets-manager-agent-extension.sh获取名为MyTest的机密,该脚本位于https://github.com/aws/aws-secretsmanager-agent,将Secrets Manager Agent作为Lambda扩展安装。

要创建一个打包Secrets Manager Agent的Lambda扩展

  1. 创建一个Python Lambda函数,该函数查询https://127.0.0.1:2773/secretsmanager/get?secretId=MyTest以获取机密。请确保在您的应用程序代码中实现重试逻辑,以适应Lambda扩展的初始化和注册延迟。

  2. 从Secrets Manager Agent代码包的根目录运行以下命令以测试Lambda扩展。

    AWS_ACCOUNT_ID=<AWS_ACCOUNT_ID>
    LAMBDA_ARN=<LAMBDA_ARN>
    
    # Build the release binary 
    cargo build --release --target=x86_64-unknown-linux-gnu
    
    # Copy the release binary into the `bin` folder
    mkdir -p ./bin
    cp ./target/x86_64-unknown-linux-gnu/release/aws_secretsmanager_agent ./bin/secrets-manager-agent
    
    # Copy the `secrets-manager-agent-extension.sh` script into the `extensions` folder.
    mkdir -p ./extensions
    cp aws_secretsmanager_agent/examples/example-lambda-extension/secrets-manager-agent-extension.sh ./extensions
    
    # Zip the extension shell script and the binary 
    zip secrets-manager-agent-extension.zip bin/* extensions/*
    
    # Publish the layer version
    LAYER_VERSION_ARN=$(aws lambda publish-layer-version \
        --layer-name secrets-manager-agent-extension \
        --zip-file "fileb://secrets-manager-agent-extension.zip" | jq -r '.LayerVersionArn')
    
    # Attach the layer version to the Lambda function
    aws lambda update-function-configuration \
        --function-name $LAMBDA_ARN \
        --layers "$LAYER_VERSION_ARN"
    
  3. 调用Lambda函数以验证机密是否正在正确检索。


第3步:使用Secrets Manager Agent检索机密

要使用代理,您调用本地Secrets Manager Agent端点,并将机密名称或ARN作为查询参数。默认情况下,Secrets Manager Agent检索机密的AWSCURRENT版本。要检索不同版本的机密,您可以设置versionStageversionId

为了帮助保护Secrets Manager Agent,您必须在每个请求中包含一个SSRF令牌头:X-Aws-Parameters-Secrets-Token。Secrets Manager Agent拒绝没有此头或具有无效SSRF令牌的请求。您可以在配置文件中自定义SSRF头名称。

Secrets Manager Agent使用AWS SDK for Rust,它使用https://docs.aws.amazon.com/sdk-for-rust/latest/dg/credentials.html。这些IAM凭证的身份决定了Secrets Manager Agent检索机密拥有的权限。

**所需权限: **

  • secretsmanager:DescribeSecret
  • secretsmanager:GetSecretValue

有关更多信息,请参阅 权限参考

重要
在将密钥值拉入Secrets Manager Agent后,任何可以访问计算环境和SSRF令牌的用户都可以从Secrets Manager Agent缓存中访问密钥。有关更多信息,请参阅 安全注意事项


[ curl ]

以下curl示例显示了如何从Secrets Manager Agent获取密钥。此示例依赖于SSRF存在于文件中,这是安装脚本存储的位置。

curl -v -H \
    "X-Aws-Parameters-Secrets-Token: $(</var/run/awssmatoken)" \
    'https://127.0.0.1:2773/secretsmanager/get?secretId=<YOUR_SECRET_ID>}'; \
    echo

[ Python ]

以下Python示例显示了如何从Secrets Manager Agent获取密钥。此示例依赖于SSRF存在于文件中,这是安装脚本存储的位置。

import requests
import json

# Function that fetches the secret from Secrets Manager Agent for the provided secret id. 
def get_secret():
    # Construct the URL for the GET request
    url = f"https://127.0.0.1:2773/secretsmanager/get?secretId=<YOUR_SECRET_ID>}"

    # Get the SSRF token from the token file
    with open('/var/run/awssmatoken') as fp:
        token = fp.read() 

    headers = {
        "X-Aws-Parameters-Secrets-Token": token.strip()
    }

    try:
        # Send the GET request with headers
        response = requests.get(url, headers=headers)

        # Check if the request was successful
        if response.status_code == 200:
            # Return the secret value
            return response.text
        else:
            # Handle error cases
            raise Exception(f"Status code {response.status_code} - {response.text}")

    except Exception as e:
        # Handle network errors
        raise Exception(f"Error: {e}")

配置Secrets Manager Agent

要更改Secrets Manager Agent的配置,创建一个 TOML 配置文件,然后调用 ./aws-secrets-manager-agent --config config.toml

以下列表显示了您可以配置Secrets Manager Agent的选项。

  • log_level – Secrets Manager Agent日志中报告的详细程度:DEBUG、INFO、WARN、ERROR或NONE。默认为INFO。
  • http_port – 本地HTTP服务器的端口,范围在1024到65535之间。默认为2773。
  • region – 用于请求的AWS区域。如果没有指定区域,Secrets Manager Agent将根据SDK确定区域。有关更多信息,请参阅 在《AWS SDK for Rust开发者指南》中指定您的凭据和默认区域
  • ttl_seconds – 缓存项的TTL(以秒为单位),范围在1到3600之间。默认为300。如果缓存大小为0,则不使用此设置。
  • cache_size – 可以存储在缓存中的最大密钥数量,范围在0到1000之间。0表示没有缓存。默认为1000。
  • ssrf_headers – Secrets Manager Agent检查SSRF令牌的头名称列表。默认为"X-Aws-Parameters-Secrets-Token, X-Vault-Token"。
  • ssrf_env_variables – Secrets Manager Agent检查SSRF令牌的环境变量名称列表。环境变量可以包含令牌或对令牌文件的引用,如下所示: AWS_TOKEN=file:///var/run/awssmatoken。默认为"AWS_TOKEN, AWS_SESSION_TOKEN"。
  • path_prefix – 用于确定请求是否为基于路径的请求的URI前缀。默认为"/v1/"。
  • max_conn – Secrets Manager Agent允许的HTTP客户端的最大连接数,范围在1到1000之间。默认为800。

日志记录

Secrets Manager Agent将错误本地记录到文件 logs/secrets_manager_agent.log。当您的应用程序调用Secrets Manager Agent以获取密钥时,这些调用将出现在本地日志中。它们不会出现在CloudTrail日志中。

当文件达到10 MB时,Secrets Manager Agent会创建一个新的日志文件,并总共存储五个日志文件。

日志不会发送到Secrets Manager、CloudTrail或CloudWatch。从Secrets Manager Agent获取密钥的请求不会出现在这些日志中。当Secrets Manager Agent调用Secrets Manager以获取密钥时,该调用将记录在CloudTrail中,其中包含用户代理字符串aws-secrets-manager-agent

您可以在 配置文件 中配置日志记录。

安全注意事项

对于代理架构,信任域是指代理端点和SSRF令牌可访问的范围,这通常是指整个主机。Secrets Manager代理的信任域应与Secrets Manager凭据可用的域相匹配,以保持相同的安全态势。例如,在Amazon EC2上,Secrets Manager代理的信任域将与使用Amazon EC2角色的凭据域相同。

对于尚未使用将Secrets Manager凭据锁定到应用程序的代理解决方案的安全意识应用程序,应考虑使用特定语言的AWS SDK或缓存解决方案。有关更多信息,请参阅获取机密

依赖项

~20–32MB
~498K SLoC