应该如何使用 Amazon Web 服务及其弹性 beantalk 将机密文件推送到 EC2 Ruby on Rails 应用程序?
Posted
技术标签:
【中文标题】应该如何使用 Amazon Web 服务及其弹性 beantalk 将机密文件推送到 EC2 Ruby on Rails 应用程序?【英文标题】:How should secret files be pushed to an EC2 Ruby on Rails application using amazon web services with their elastic beanstalk? 【发布时间】:2012-12-08 11:38:22 【问题描述】:如何使用 Amazon Web 服务及其弹性 beantalk 将机密文件推送到 EC2 Ruby on Rails 应用程序?
我将文件添加到 git 存储库,然后推送到 github,但我想将我的秘密文件保留在 git 存储库之外。我正在使用以下方式部署到 aws:
git aws.push
以下文件在 .gitignore 中:
/config/database.yml
/config/initializers/omniauth.rb
/config/initializers/secret_token.rb
按照此链接,我尝试将 S3 文件添加到我的部署中: http://docs.amazonwebservices.com/elasticbeanstalk/latest/dg/customize-containers.html
引用该链接:
示例代码段
以下示例从 Amazon S3 存储桶下载一个 zip 文件并将其解压缩到 /etc/myapp:
sources: /etc/myapp: http://s3.amazonaws.com/mybucket/myobject
按照这些指示,我将文件上传到 S3 存储桶,并将以下内容添加到 .ebextensions 目录中的 private.config 文件中:
sources:
/var/app/current/: https://s3.amazonaws.com/mybucket/config.tar.gz
该 config.tar.gz 文件将解压到:
/config/database.yml
/config/initializers/omniauth.rb
/config/initializers/secret_token.rb
但是,在部署应用程序时,S3 主机上的 config.tar.gz 文件永远不会被复制或提取。我仍然收到找不到 database.yml 的错误,并且 EC2 日志没有配置文件的记录,这是错误消息:
Error message:
No such file or directory - /var/app/current/config/database.yml
Exception class:
Errno::ENOENT
Application root:
/var/app/current
【问题讨论】:
【参考方案1】:从那里安全文档 Amazon EC2 支持用于文件加密的 TrueCrypt 和用于传输数据的 SSL。查看这些文件
Security Whitepaper Features Risk and Compliance Best Practices您可以上传带有加密磁盘的服务器实例,也可以使用私有仓库(我认为这对 github 来说是成本,但还有其他选择)
【讨论】:
嗯,我认为这里最重要的事情之一是确保存在正确的权限,并且从 S3 请求文件的应用程序具有正确的权限,但两者都在我的用户下运行,我有文件的权限,所以我不确定如何判断这是否是问题。【参考方案2】:我认为您想要做的“正确”方法是使用 IAM 角色。你可以在这里看到一篇关于它的博文:http://aws.typepad.com/aws/aws-iam/
基本上,它允许您启动 EC2 实例,而无需在任何配置文件中放置任何个人凭证。当您启动实例时,它将被分配给定的角色(一组使用 AWS 资源的权限),并且将使用 Amazon IAM 自动在机器上放置一个轮换凭证。
【讨论】:
【参考方案3】:使用环境变量是一个好方法。在环境中引用密码,所以在一个yaml文件中:
password: <%= ENV['DATABASE_PASSWORD'] %>
然后直接使用 eb 或控制台在实例上设置它们。
您可能担心在环境中容易获得此类敏感信息。如果某个进程破坏了您的系统,无论它在哪里,它都可能获得密码。 Heroku 等许多 PaaS 提供商都使用这种方法。
【讨论】:
【参考方案4】:为了让.ebextension/*.config
文件能够从 S3 下载文件,它们必须是公开的。鉴于它们包含敏感信息,这是一个坏主意。
您可以启动 Elastic Beanstalk 实例 with an instance role,并且可以授予该角色访问相关文件的权限。不幸的是,.ebextension/*.config
文件的 file:
和 sources:
部分没有使用此角色的直接访问权限。
您应该能够使用AWS SDK for Ruby 的AWS::S3::S3Object 类编写一个简单的脚本来下载文件,并使用command:
而不是sources:
。如果不指定凭据,SDK 会自动尝试使用该角色。
您必须为您的角色添加一个策略,允许您专门下载您感兴趣的文件。它看起来像这样:
"Statement": [
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::mybucket/*"
]
然后你可以在你的 .config
文件中做这样的事情
files:
/usr/local/bin/downloadScript.rb: http://s3.amazonaws.com/mybucket/downloadScript.rb
commands:
01-download-config:
command: ruby /usr/local/downloadScript.rb http://s3.amazonaws.com/mybucket/config.tar.gz /tmp
02-unzip-config:
command: tar xvf /tmp/config.tar.gz
cwd: /var/app/current
【讨论】:
【参考方案5】:我认为最好的方法是不要破解 AWS(设置挂钩、上传文件)。只需使用 ENV 变量。
使用 gem 'dot-env' 进行开发(即 'config/database.yml' 中的 )和默认 AWS 控制台在 Beanstalk 中设置变量。
【讨论】:
【参考方案6】:在 S3 中存储敏感文件并自动将它们复制到您的 Beanstalk 实例是可能的(并且很容易)。
当您创建 Beanstalk 应用程序时,会自动创建一个 S3 存储桶。该桶用于存储应用版本、日志、元数据等。
分配给您的 Beanstalk 环境的默认 aws-elasticbeanstalk-ec2-role
具有对该存储桶的读取权限。
因此,您只需将敏感文件放在该存储桶中(在存储桶的根目录或您想要的任何目录结构中),然后创建一个.ebextension
配置文件以将它们复制到您的 EC2 实例.
这是一个例子:
# .ebextensions/sensitive_files.config
Resources:
AWSEBAutoScalingGroup:
Metadata:
AWS::CloudFormation::Authentication:
S3Auth:
type: "s3"
buckets: ["elasticbeanstalk-us-east-1-XXX"] # Replace with your bucket name
roleName:
"Fn::GetOptionSetting":
Namespace: "aws:autoscaling:launchconfiguration"
OptionName: "IamInstanceProfile"
DefaultValue: "aws-elasticbeanstalk-ec2-role" # This is the default role created for you when creating a new Beanstalk environment. Change it if you are using a custom role
files:
/etc/pki/tls/certs/server.key: # This is where the file will be copied on the EC2 instances
mode: "000400" # Apply restrictive permissions to the file
owner: root # Or nodejs, or whatever suits your needs
group: root # Or nodejs, or whatever suits your needs
authentication: "S3Auth"
source: https://s3-us-west-2.amazonaws.com/elasticbeanstalk-us-east-1-XXX/server.key # URL to the file in S3
这在此处记录:http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/https-storingprivatekeys.html
【讨论】:
【参考方案7】:我知道这是一篇旧帖子,但我无法在任何地方找到另一个答案,所以我熬夜才想出一个。我希望它可以为您节省几个小时。
我同意开发人员的意见,他们发布了多少 PITA 来强制开发人员将 ENV 变量放入他们的本地 dev database.yml 中。我知道 dotenv gem 很好,但您仍然需要维护 ENV 变量,这会增加启动站所需的时间。
我的方法是在 S3 上由 EB 创建的存储桶中存储一个 database.yml 文件,然后使用 .ebextensions 配置文件在服务器的 pre hook 目录中创建一个脚本,以便在解压缩到暂存后执行目录,但在资产编译之前——当然,没有 database.yml 就会爆炸。
.config 文件是
# .ebextensions/sensitive_files.config
# Create a prehook command to copy database.yml from S3
files:
"/opt/elasticbeanstalk/hooks/appdeploy/pre/03_copy_database.sh" :
mode: "000755"
owner: root
group: root
content: |
#!/bin/bash
set -xe
EB_APP_STAGING_DIR=$(/opt/elasticbeanstalk/bin/get-config container -k app_staging_dir)
echo EB_APP_STAGING_DIR is $EB_APP_STAGING_DIR >/tmp/copy.log
ls -l $EB_APP_STAGING_DIR >>/tmp/copy.log
aws s3 cp s3://elasticbeanstalk-us-east-1-XXX/database.yml $EB_APP_STAGING_DIR/config/database.yml >>/tmp/copy.log 2>>/tmp/copy.log
注意事项
当然bucket名称中的XXX是EB创建的序列号。您必须检查 S3 才能看到存储桶的名称。 我创建的脚本文件的名称很重要。这些脚本是按字母顺序执行的,所以我很小心地给它命名,所以它排在asset_compilation 脚本之前。 显然将输出重定向到 /tmp/copy.log 是可选的对我帮助最大的帖子是Customizing ElasticBeanstalk deployment hooks
由 Kenta@AWS 发布。谢谢健太!
【讨论】:
以上是关于应该如何使用 Amazon Web 服务及其弹性 beantalk 将机密文件推送到 EC2 Ruby on Rails 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章
适用于 iOS 消费的 Web 服务(在 Amazon 上)安全性