AWS Elastic Beanstalk 无法解析 Secrets Manager 中的机密

问题描述 投票:0回答:1

我按照 https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/single-container-docker-configuration.html#docker-configuration.remote-repo 的说明从 Secrets 注入机密管理器(“使用 AWS Secrets Manager”部分)

我在 Elastic Beanstalk 上使用 Docker 平台

arn:aws:elasticbeanstalk:ap-southeast-2::platform/Docker running on 64bit Amazon Linux 2/3.6.1

我在 Secrets Manager 中有以下秘密 blob,名为“AppSecret”

{ "username": "Bruce.Wayne", "password": "I_AM_BATMAN" }

.ebextensions/options.config
我有以下内容

option_settings:
  aws:elasticbeanstalk:application:environment:
    USER: '{{resolve:secretsmanager:AppSecret:SecretString:username}}'
    PASSWORD: '{{resolve:secretsmanager:AppSecret:SecretString:password}}'

我还有一个

.platform/hooks/postdeploy/dump.sh
(用于测试),其中包含

#! /usr/bin/env bash

echo "PASSWORD $(/opt/elasticbeanstalk/bin/get-config environment -k PASSWORD)"

IAM 角色 (

aws-elasticbeanstalk-ec2-role
) 附加了
SecretsManagerReadWrite
策略,其中包含 IAM 操作
"secretsmanager:*"
。这应该满足要求(来自https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/dynamic-references.html#dynamic-references-secretsmanager

要指定存储在 Secrets Manager 中的密钥,您必须有权调用该密钥的 GetSecretValue。

问题在于,当 ZIP 部署到 Elastic Beanstalk 时,秘密并未得到解析。日志的输出

eb-hooks.log

PASSWORD {{resolve:secretsmanager:AppSecret:SecretString:password}}

同样的

options.config
已正确解析 SSM 引用,只是
secretsmanager
失败了。

这可能是云形成的一些模糊部分,或者是我忽略的简单部分,但我不知道为什么会失败。

(或者,如果有人可以指导我如何将 SSM SecureString 与 Elastic Beanstalk 结合使用,那就更好了)

amazon-web-services amazon-ec2 amazon-elastic-beanstalk aws-cloudformation aws-secrets-manager
1个回答
0
投票

最近我面临着同样的挑战,如何在我的应用程序中传递凭据。弹性豆茎确实不能解开秘密。有几种方法可以做到这一点。我要分享一个对我有用的。

先决条件 您在 Elastic Beanstalk 中的 IAM 角色应该能够检索机密。 下面我将向您提供 CloudFormation 堆栈,我在其中添加了我的 Elastic Beanstalk IAM 角色,并授予其从 AWS Secret Manager 检索密钥的权限,密钥名称为 name/ofyoursecret/db

EBInstanceRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: 'ec2.amazonaws.com'
            Action: 'sts:AssumeRole'
      Path: '/'
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AWSElasticBeanstalkWebTier'
      Policies:
        - PolicyName: 'AdditionalPermissions'
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: 'secretsmanager:GetSecretValue'
                Resource: !Sub 'arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:name/ofyoursecret/db*'
              - Effect: Allow
                Action: 'ecr:GetAuthorizationToken'
                Resource: "*"
              - Effect: Allow
                Action: 
                  - 'ecr:BatchCheckLayerAvailability'
                  - 'ecr:GetDownloadUrlForLayer'
                  - 'ecr:GetRepositoryPolicy'
                  - 'ecr:DescribeRepositories'
                  - 'ecr:ListImages'
                  - 'ecr:DescribeImages'
                  - 'ecr:BatchGetImage'
                Resource:
                  - !Sub 'arn:aws:ecr:${AWS::Region}:${AWS::AccountId}:repository/name-repository*'


  EBInstanceProfile:
    Type: 'AWS::IAM::InstanceProfile'
    Properties:
      Path: "/"
      Roles:
        - !Ref EBInstanceRole
        
  ElasticBeanstalkApplication:
    Type: 'AWS::ElasticBeanstalk::Application'
    Properties:
      ApplicationName: !Ref Project

  ElasticBeanstalkEnvironment:
    Type: 'AWS::ElasticBeanstalk::Environment'
    Properties:
      EnvironmentName: !Sub '${Project}-${Environment}'
      ApplicationName: !Ref ElasticBeanstalkApplication
      SolutionStackName: '64bit Amazon Linux 2 v3.7.1 running Docker'
      OptionSettings:
        - Namespace: 'aws:elasticbeanstalk:application:environment'
          OptionName: 'HOST_URL'
          Value: !ImportValue 
            'Fn::Sub': "${Environment}-${Project}-DBEndpoint"
        - Namespace: 'aws:elasticbeanstalk:application:environment'
          OptionName: 'DATABASE_SECRET_ARN'
          Value: !Sub 'arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:name/ofyoursecret/db'

现在我将使用 sh 脚本从 AWS Secret Manager 检索密钥。因为我传入了环境变量 DATABASE_SECRET_ARN,所以它是我的密钥的 ARN(Amazon 资源名称 (ARN) 不是密钥) 我在这里传递了数据库主机 URL。

获取_credentials.sh

#!/bin/sh

# Get the AWS region from EC2 instance metadata
AWS_REGION=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed 's/[a-zA-Z]$//')

# Check if AWS_REGION is obtained successfully
if [ -z "$AWS_REGION" ]; then
    echo "Failed to get AWS region from EC2 metadata."
    exit 1
fi

# Get DATABASE_SECRET_ARN and HOST_URL from environment variables
DATABASE_SECRET_ARN=$(printenv DATABASE_SECRET_ARN)
HOST_URL=$(printenv HOST_URL)

if [ -z "$DATABASE_SECRET_ARN" ]; then
    echo "DATABASE_SECRET_ARN environment variable not found."
    exit 1
fi

if [ -z "$HOST_URL" ]; then
    echo "HOST_URL environment variable not found."
    exit 1
fi

# Use AWS CLI to get the secret value
SECRET_STRING=$(aws secretsmanager get-secret-value --secret-id $DATABASE_SECRET_ARN --region $AWS_REGION --query SecretString --output text)

# Check if SECRET_STRING is obtained successfully
if [ -z "$SECRET_STRING" ]; then
    echo "Failed to retrieve secret string from Secrets Manager."
    exit 1
fi

# Extract credentials from SECRET_STRING
USERNAME=$(echo $SECRET_STRING | jq -r .username)
DBPASSWORD=$(echo $SECRET_STRING | jq -r .dbpassword)
DBNAME=$(echo $SECRET_STRING | jq -r .dbname)

# Optionally, export DATABASE_URL to be available to other processes started by this script
export DATABASE_URL="postgresql+asyncpg://${USERNAME}:${DBPASSWORD}@${HOST_URL}:5432/${DBNAME}"

在我的 Dockerfile 中,我使用入口点脚本并在 .env 文件中传递我的值

入口点.sh

   #!/bin/sh

echo "Starting the entrypoint script at $(date)"
echo "Sourcing get_cred_db.sh to set environment variables..."
. ./get_credentials.sh

# Assuming get_cred_db.sh successfully sets and exports DATABASE_URL
# Now, write DATABASE_URL and potentially other environment variables to a .env file
echo "DATABASE_URL=$DATABASE_URL" > /usr/src/app/.env


echo "Environment variables recorded in .env file."

# Execute the passed command
exec "$@"
© www.soinside.com 2019 - 2024. All rights reserved.