将 EC2 用户数据 shell 脚本存储在私有 S3 存储桶中是否安全?
Is it secure to store EC2 User-Data shell scripts in a private S3 bucket?
我在 AWS 上有一个 EC2 ASG,我有兴趣存储 shell 脚本,该脚本用于在 S3 存储桶中实例化任何给定实例并下载它并在实例化时 运行,但即使我使用 IAM Instance Role
,通过 HTTPS 传输,并在 S3 存储桶 中使用 KMS
[=104 加密脚本本身,这一切都感觉有点摇摇欲坠=] 使用 S3 Server Side Encryption
(because the KMS
method was throwing an 'Unknown' error)。
设置
- 创建了一个
IAM Instance Role
,它在实例化时分配给我的 ASG 中的任何实例,导致我的 AWS 凭证作为 ENV
vars 被烘焙到实例中
- 已将我的
Instance-Init.sh
脚本上传并加密到 S3,生成如下私有端点:https://s3.amazonaws.com/super-secret-bucket/Instance-Init.sh
在 User-Data
字段中
我在创建 Launch Configuration
时在 User Data
字段中输入以下内容 我希望我的 ASG 使用:
#!/bin/bash
apt-get update
apt-get -y install python-pip
apt-get -y install awscli
cd /home/ubuntu
aws s3 cp s3://super-secret-bucket/Instance-Init.sh . --region us-east-1
chmod +x Instance-Init.sh
. Instance-Init.sh
shred -u -z -n 27 Instance-Init.sh
以上执行以下操作:
- 更新包列表
- 安装 Python(需要 运行
aws-cli
)
- 安装
aws-cli
- 更改
/home/ubuntu
用户目录
- 使用
aws-cli
从 S3
下载 Instance-Init.sh
文件。由于 IAM Role
分配给我的实例,我的 AWS 凭据被 aws-cli
自动发现。 IAM Role
还授予我的实例解密文件所需的权限。
- 使其可执行
- 运行脚本
- 完成后删除脚本。
Instance-Init.sh
脚本
脚本本身会做一些事情,比如设置 env
vars 和 docker run
我需要在我的实例上部署的容器。有点像:
#!/bin/bash
export MONGO_USER='MyMongoUserName'
export MONGO_PASS='Top-Secret-Dont-Tell-Anyone'
docker login -u <username> -p <password> -e <email>
docker run - e MONGO_USER=${MONGO_USER} -e MONGO_PASS=${MONGO_PASS} --name MyContainerName quay.io/myQuayNameSpace/MyAppName:latest
非常好用
这创建了一种非常方便的方法来更新 User-Data
脚本,而无需在每次需要进行微小更改时创建新的 Launch Config
。它很好地将 env
变量从你的代码库中提取出来,变成一个狭窄的、可控的 space(Instance-Init.sh
脚本本身)。
但这一切都让人觉得有点不安全。将我的主数据库凭据放入 S3 上的文件中的想法至少可以说是令人不安的。
问题
- 这是一种常见的做法还是我想出了一个坏主意?
- 文件在新实例上下载并存储(虽然时间很短)这一事实是否构成漏洞?
- 有没有更好的方法可以更安全的删除文件?
- 文件在运行之后是否删除有关系吗?考虑到秘密正在转移到
env
变量,删除 Instance-Init.sh
文件似乎是多余的。
- 在我刚刚开始的运维生涯中,有什么东西是我遗漏的吗?
提前感谢您的帮助。
您所描述的几乎正是我们用来从注册表中实例化 Docker 容器的内容(我们现在使用 v2 self-hosted/private、s3-backed docker-registry 而不是码头)投入生产。 FWIW,我有同样的 "this feels rickety" 感觉,就像你第一次踏上这条路时所描述的,但在做了将近一年之后——与将这些敏感配置数据存储在 repo 中或烘焙到图片——我相信这是处理这些数据的更好方法之一。现在,话虽这么说,我们目前正在考虑使用 Hashicorp's new Vault software 来部署配置机密,以替换此 "shared" 加密机密 shell 脚本容器(据说快五倍)。我们认为 Vault 将相当于将加密外包给开源社区(它所属的地方),但用于配置存储。
简而言之,我们已经使用了大约一年的时间,但我们还没有 运行 解决很多问题,情况非常相似,但我们现在正在考虑使用外部开源项目(Hashicorp 的Vault) 来替换我们自己开发的方法。祝你好运!
Vault 的替代方法是使用 credstash,它利用 AWS KMS 和 DynamoDB 来实现类似的目标。
我实际上使用 credstash 通过一个简单的入口点脚本在容器启动时动态导入敏感配置数据 - 这样敏感数据就不会通过 docker 检查或 docker 日志等公开。
这是一个示例入口点脚本(用于 Python 应用程序)- 这里的优点是您仍然可以通过环境变量为 non-AWS/dev 环境传递凭据。
#!/bin/bash
set -e
# Activate virtual environment
. /app/venv/bin/activate
# Pull sensitive credentials from AWS credstash if CREDENTIAL_STORE is set with a little help from jq
# AWS_DEFAULT_REGION must also be set
# Note values are Base64 encoded in this example
if [[ -n $CREDENTIAL_STORE ]]; then
items=$(credstash -t $CREDENTIAL_STORE getall -f json | jq 'to_entries | .[]' -r)
keys=$(echo $items | jq .key -r)
for key in $keys
do
export $key=$(echo $items | jq 'select(.key=="'$key'") | .value' -r | base64 --decode)
done
fi
exec $@
我在 AWS 上有一个 EC2 ASG,我有兴趣存储 shell 脚本,该脚本用于在 S3 存储桶中实例化任何给定实例并下载它并在实例化时 运行,但即使我使用 IAM Instance Role
,通过 HTTPS 传输,并在 S3 存储桶 中使用 KMS
[=104 加密脚本本身,这一切都感觉有点摇摇欲坠=] 使用 S3 Server Side Encryption
(because the KMS
method was throwing an 'Unknown' error)。
设置
- 创建了一个
IAM Instance Role
,它在实例化时分配给我的 ASG 中的任何实例,导致我的 AWS 凭证作为ENV
vars 被烘焙到实例中
- 已将我的
Instance-Init.sh
脚本上传并加密到 S3,生成如下私有端点:https://s3.amazonaws.com/super-secret-bucket/Instance-Init.sh
在 User-Data
字段中
我在创建 Launch Configuration
时在 User Data
字段中输入以下内容 我希望我的 ASG 使用:
#!/bin/bash
apt-get update
apt-get -y install python-pip
apt-get -y install awscli
cd /home/ubuntu
aws s3 cp s3://super-secret-bucket/Instance-Init.sh . --region us-east-1
chmod +x Instance-Init.sh
. Instance-Init.sh
shred -u -z -n 27 Instance-Init.sh
以上执行以下操作:
- 更新包列表
- 安装 Python(需要 运行
aws-cli
) - 安装
aws-cli
- 更改
/home/ubuntu
用户目录 - 使用
aws-cli
从S3
下载Instance-Init.sh
文件。由于IAM Role
分配给我的实例,我的 AWS 凭据被aws-cli
自动发现。IAM Role
还授予我的实例解密文件所需的权限。 - 使其可执行
- 运行脚本
- 完成后删除脚本。
Instance-Init.sh
脚本
脚本本身会做一些事情,比如设置 env
vars 和 docker run
我需要在我的实例上部署的容器。有点像:
#!/bin/bash
export MONGO_USER='MyMongoUserName'
export MONGO_PASS='Top-Secret-Dont-Tell-Anyone'
docker login -u <username> -p <password> -e <email>
docker run - e MONGO_USER=${MONGO_USER} -e MONGO_PASS=${MONGO_PASS} --name MyContainerName quay.io/myQuayNameSpace/MyAppName:latest
非常好用
这创建了一种非常方便的方法来更新 User-Data
脚本,而无需在每次需要进行微小更改时创建新的 Launch Config
。它很好地将 env
变量从你的代码库中提取出来,变成一个狭窄的、可控的 space(Instance-Init.sh
脚本本身)。
但这一切都让人觉得有点不安全。将我的主数据库凭据放入 S3 上的文件中的想法至少可以说是令人不安的。
问题
- 这是一种常见的做法还是我想出了一个坏主意?
- 文件在新实例上下载并存储(虽然时间很短)这一事实是否构成漏洞?
- 有没有更好的方法可以更安全的删除文件?
- 文件在运行之后是否删除有关系吗?考虑到秘密正在转移到
env
变量,删除Instance-Init.sh
文件似乎是多余的。 - 在我刚刚开始的运维生涯中,有什么东西是我遗漏的吗?
提前感谢您的帮助。
您所描述的几乎正是我们用来从注册表中实例化 Docker 容器的内容(我们现在使用 v2 self-hosted/private、s3-backed docker-registry 而不是码头)投入生产。 FWIW,我有同样的 "this feels rickety" 感觉,就像你第一次踏上这条路时所描述的,但在做了将近一年之后——与将这些敏感配置数据存储在 repo 中或烘焙到图片——我相信这是处理这些数据的更好方法之一。现在,话虽这么说,我们目前正在考虑使用 Hashicorp's new Vault software 来部署配置机密,以替换此 "shared" 加密机密 shell 脚本容器(据说快五倍)。我们认为 Vault 将相当于将加密外包给开源社区(它所属的地方),但用于配置存储。
简而言之,我们已经使用了大约一年的时间,但我们还没有 运行 解决很多问题,情况非常相似,但我们现在正在考虑使用外部开源项目(Hashicorp 的Vault) 来替换我们自己开发的方法。祝你好运!
Vault 的替代方法是使用 credstash,它利用 AWS KMS 和 DynamoDB 来实现类似的目标。
我实际上使用 credstash 通过一个简单的入口点脚本在容器启动时动态导入敏感配置数据 - 这样敏感数据就不会通过 docker 检查或 docker 日志等公开。
这是一个示例入口点脚本(用于 Python 应用程序)- 这里的优点是您仍然可以通过环境变量为 non-AWS/dev 环境传递凭据。
#!/bin/bash
set -e
# Activate virtual environment
. /app/venv/bin/activate
# Pull sensitive credentials from AWS credstash if CREDENTIAL_STORE is set with a little help from jq
# AWS_DEFAULT_REGION must also be set
# Note values are Base64 encoded in this example
if [[ -n $CREDENTIAL_STORE ]]; then
items=$(credstash -t $CREDENTIAL_STORE getall -f json | jq 'to_entries | .[]' -r)
keys=$(echo $items | jq .key -r)
for key in $keys
do
export $key=$(echo $items | jq 'select(.key=="'$key'") | .value' -r | base64 --decode)
done
fi
exec $@