【问题标题】:Setting up private Github access with AWS Elastic Beanstalk and Ruby container使用 AWS Elastic Beanstalk 和 Ruby 容器设置私有 Github 访问
【发布时间】:2012-11-08 16:38:32
【问题描述】:

通过recent tutorial 使用 Git 为 Ruby 部署设置 AWS Elastic Beanstalk,我刚刚从我的 CI 服务器设置了一个 Elastic Beanstalk 环境。但是,应用程序无法启动。我查看了日志,发现 bundle install 失败并显示错误消息。

获取 git@github.com:example/private-repository.git 主机密钥验证失败。 致命:远端意外挂断 [31mGit 错误:/var/app/ondeck 目录中的命令git clone 'git@github.com:example/private-repository.git' "/var/app/ondeck/vendor/cache/ruby/1.9.1/cache/bundler/git/private-repository-e4bbe6c2b13bb62664e39e345c1b01d80017934c" --bare --no-hardlinks 失败。[0m

我的 Rails 应用程序的Gemfile 包含对托管在我在 Github 上的几个私有存储库上的 gemified 插件的引用。类似的东西

gem 'somegemname', :git => 'git@github.com:example/private-repository.git'

我在 Capistrano 部署中遇到过类似问题,通过设置 ssh_options[:forward_agent] = true 解决了这些问题。

AWS Elastic Beanstalk Ruby 容器支持通过放在.ebextensions 下的自定义.config 文件进行自定义配置。在这种情况下,设置 SSH 转发代理会有所帮助吗?在启动 Elastic Beanstalk 环境时,是否有其他替代方法可以访问私有 Github 存储库?

更新 1: 我刚刚检查了启动bundle install 的用户。发现脚本/opt/elasticbeanstalk/hooks/appdeploy/pre/10_bundle_install.shroot 用户身份启动bundle install。我尝试在/root/.ssh 下创建一个 SSH 密钥,并将它的 pub-key 添加到该存储库的 Github Deploy 密钥中。到目前为止没有运气。现在将尝试将 SSH 发布密钥添加到我在 Github 上的用户帐户,以便它适用于通过我的 Github 帐户访问的所有私有存储库。

【问题讨论】:

    标签: ruby-on-rails ruby amazon-web-services amazon-elastic-beanstalk


    【解决方案1】:

    经过一天的努力,我终于通过使用 .config 文件来启用我组织的私有 GitHub 存储库和 Elastic Beanstalk。我正在使用 Python 和 pip,但它也应该适用于 EB 上的其他包安装程序。

    rhetonik 的 ssh-agent+ssh-add 方法对我根本不起作用,所以我选择设置一个 ssh 配置文件。

    这是我的.ebextensions/3-pip-install-from-github.config 文件:

    files:
        "/root/.ssh/config":
            owner: root
            group: root
            mode: "000600"
            content: |
                Host github.com
                    User git
                    Hostname github.com
                    IdentityFile /root/.ssh/github
    
    commands:
        01-command:
            command: sudo ssh-keyscan -H github.com >> /root/.ssh/known_hosts
        02-command:
            command: sudo chmod 644 /root/.ssh/known_hosts
        03-command:
            command: sudo aws s3 cp s3://bucket-with-your-github-ssh-key/github /root/.ssh
        04-command:
            command: sudo chmod 600 /root/.ssh/github
    

    粗略说明:

    • Set up an S3 bucket accessible by your EB instance。在该存储桶内,存储 SSH 密钥,允许通过 pipnpmbundle 等访问您想要访问的 GitHub 存储库。使用 sudo aws s3 cp 将该密钥复制到部署时的 EB 实例上。 sudo 是必需的,因为 EB 脚本使用 root 而不是 ec2-user

    • 此 ebextensions 配置文件还会在您的 EB 实例上创建 2 个文件。 /root/.ssh/config 告诉 ssh(由 pipgit 调用)使用您从 S3 复制的密钥。将ssh-keyscan -H github.com 的输出存储到/root/.ssh/known_hosts 将预先验证您的EB 实例上的ssh 实际上正在与GitHub 通信以避免MITM 攻击。这比在/root/.ssh/config 中禁用StrictHostKeyChecking 要好。

    这是我的requirements.txtpip 文件:

    Beaker==1.7.0
    Flask==0.10.1
    Jinja2==2.7.3
    MarkupSafe==0.23
    # [...]
    git+ssh://git@github.com/myorganization/myprivaterepo.git@0.0.142
    

    在运行eb-deploy 时,您可以tail -f /var/log/eb-activity.log 确保一切顺利运行。

    【讨论】:

    • 这是一个很好的答案,谢谢分享。由于某些原因,此解决方案对我不起作用:ssh 一直在向我询问密钥文件的密码,但它没有密码。这是我的ssh -v github.com 的输出: debug1: Trying private key: /root/.ssh/github debug1: key_parse_private2: missing begin marker debug1: key_parse_private_pem: PEM_read_PrivateKey failed debug1: read PEM private key done: type Enter passphrase for key '/root/.ssh/github':
    • 'ssh-keyscan -H github.com' 的输出,你能添加一个例子吗?添加我自己的输出时不确定我的语法是否正确。
    • 这救了我的命。非常感谢。在其他地方找到的建议建议 git 将在 EB 上使用的 .ssh 折叠应位于 /tmp 或 /home/ec2-user 下,我挣扎了一整天。把它放在 /root 下解决了我所有的问题。我的相关问题是stackoverflow.com/questions/43497663/…谢谢!
    • 感谢您的出色回答,为我节省了很多时间:)。这是您可以添加的改进,这要归功于您回答后出现的一些 ElasticBeanstalk 新功能:现在可以通过 files 指令而不是命令来从 SSH 密钥文件下载:请参阅 AWS-EB 上的最后一个示例定制文档:docs.aws.amazon.com/elasticbeanstalk/latest/dg/…
    • “设置您的 EB 实例可访问的 S3 存储桶。”你能解释一下怎么做吗?
    【解决方案2】:

    这就是我最终做到的方式。这一切都是为了为负责bundle install 阶段的用户设置一个 SSH 密钥。

    1. 在 AWS Elastic Beanstalk 中为应用程序启动环境
    2. 可选 - 登录 Amazon EC2 控制台并将实例类型更改为所需值
    3. 更新 SSH 密钥对名称以启用远程 SSH 登录。 (我确信在启动环境时必须有一种方法来指定实例类型和 SSH 密钥对名称)
    4. 在 EC2 控制台或通过 CLI 查找新启动的实例,注意此实例的完全限定域名 (FQDN)。 EB 实例与您使用 Amazon EC2 创建的任何其他实例一样。通过 SSH 登录到此实例。
    5. 执行以下命令为root用户创建SSH密钥

      $ sudo su - 根

      $ ssh-keygen -t rsa -C "some-email@yourdomain.com"

    6. 编辑 .bash_profile 以显式启动 ssh-agent 并添加新生成的 SSH 密钥。添加以下几行(这似乎没有必要,我这样做只是为了确定)

      eval `ssh-agent

      评估ssh-add ~/.ssh/id_rsa

    7. 记下 SSH 公钥,例如:~/.ssh/id_rsa.pub 并将其添加到有权访问私有存储库的 Github 帐户的 SSH 密钥集

    8. 此时,您的实例可以访问您的私有 Github 存储库。您可以通过以root 用户身份登录在这些存储库上发出git clone 来测试这一点。

    9. 使用标准方法从此实例创建 AMI

    10. 返回您的 AWS Elastic Beanstalk 仪表板并在您的应用程序环境中查找 Edit Configuration 选项。在Server 选项卡中,查找可让您指定Custom AMI 的选项。使用新创建的 AMI ID 更新此字段,例如:ami-4324fd4

    11. 点击Apply Changes保存配置。 AWS Elastic Beanstalk 将开始在您的环境中部署新实例并终止旧实例。这是为了确保您的所有自动扩展实例都拥有私有 Github 访问所需的列入白名单的 SSH 密钥。

    完成上述步骤后,您可以继续使用git aws.push 部署您的Rails 应用程序

    希望这可以帮助其他陷入困境的人。不过,我很高兴看到比这个更优雅的解决方案。

    【讨论】:

    • 嘿,谢谢你分享这个。我有一个关于将自定义 AMI 与 Elastic Beanstalk 一起使用的问题,您是否仍会获得此 AMI 的安全更新?
    • @YannMilin:对延迟回复表示歉意。恐怕,我还没有尝试过。但我认为,只要您运行基本操作系统,您就应该继续收到安全更新。
    • 很高兴看到一个功能性.ebextensions/[name].conf 文件的示例可以完成此操作。
    • 截至 16 年,此解决方案已过时,而且从来都不是最佳解决方案,因为它需要在实例上进行手动更改。每次亚马逊发布新版本实例时,都必须重复程序才能使用它。此外,适当的解决方案不应要求登录到实例。理想情况下,不应存在在 Elastic Beanstalk 实例上进行 SSH 登录的可能性。
    【解决方案3】:

    如果您赶时间,并且您的应用程序仓库也是私有的,您可以创建一个额外的 Github 用户帐户并将其分配给包含 gem 的仓库的只读权限。

    然后将带有新帐户凭据的 https url 提供给 bundler:

    gem 'somegemname', git: "https://username:password@github.com/example/privaterepository"
    

    【讨论】:

      【解决方案4】:

      使用 GitHub 进行身份验证有两种方法。无论哪种情况,我都建议将您的个人 GitHub 帐户与私有 GitHub 存储库相关联。

      第一种方法传递您在本地用于从远程 GitHub 存储库推送、拉取等的相同 ssh 凭据——您为您的个人帐户上传了公钥,这就是 GitHub 使用的。要在另一台服务器上运行此功能,您需要运行 ssh-agent 并使用 ssh-add 将您的密钥添加到代理 - 然后您的个人 GitHub 凭据可用于执行 git 命令。

      第二种方法是允许您部署到的远程服务器访问 GitHub——这可能是弹性 beanstalk 或您的实际服务器。在服务器上创建一个无密码的 ssh 密钥(ssh-keygen -t rsa,接受默认值,或者 EB 可能有自己的方法)然后复制生成的公钥内容并在您的 GitHub 存储库中创建一个包含该密钥的新“部署密钥”——你需要成为管理员,我假设你是。已安装的部署密钥将允许 EB 用户登录远程服务器并从服务器执行git pull 和相关命令(只读)。

      我认为随着您要部署到的服务器数量的增加,第一种方法更优雅且更易于管理,但您使用哪种方法可能取决于 EB 的选项。

      【讨论】:

      • 如前所述,Capistrano 是我之前使用的东西,这些问题已通过ssh_options 解决。在这里,我尝试使用 AWS Elastic Beanstalk 设置相同的 Rails 项目。不幸的是,部署似乎没有在任何地方涉及 Capistrano。
      • 啊,对不起,我看错了。我会编辑答案,虽然没有 capistrano 的东西会说几乎一样的东西
      • 是的,我一直在考虑 Github 允许的部署密钥。但是,我必须创建一个自定义 AMI 或至少一个自定义 .ebextensions 配置以适应此更改。我正在尝试找出实现它的最佳方法。
      【解决方案5】:

      从您的 requirements.txt 文件中删除私有 github 存储库,并创建一个脚本以使用用户名和密码的环境变量来安装它们。

      文件:project-root/install-extra-requirements.sh

      #!/bin/sh
      
      source /opt/python/run/venv/bin/activate
      python ".extra-requirements.py"
      

      文件:project-root/.extra-requirements.py

      import os
      
      def main():
          github_username = os.environ['GITHUB_USERNAME']
          github_password = os.environ['GITHUB_PASSWORD']
          repository = "git+https://%s:%s@github.com/yourgithubrepo" % (github_username, github_password)
          os.system("pip install %s" % repository)
      
      if __name__ == '__main__':
          main()
      

      文件:project-root/.ebextensions/002_container.config

      container_commands:
        01_install_extra_requirements:
          command: './install-extra-requirements.sh'
      

      现在您可以在弹性 beanstalk 环境中将 GITHUB_USERNAME 和 GITHUB_PASSWORD 设置为环境变量。

      【讨论】:

      • 通过 env var 暴露密码是不好的做法。应该使用 AWS Secrets Manager。
      猜你喜欢
      • 2017-09-15
      • 2014-03-22
      • 2017-01-01
      • 2017-07-26
      • 2019-10-01
      • 2021-11-25
      • 2021-08-22
      • 2017-04-20
      相关资源
      最近更新 更多