使用AmazonLinux2挂钩配置ElasticBeanstalk以便SSH访问私有gitrepo



假设我们在github或bitbucket上托管的私有存储库中有一个名为shared_package的自定义Python包。我们的私有存储库被配置为通过SSH进行只读访问,例如这里描述的github和这里描述的bitbucket。

我们的另一个项目,恰当地命名为dependent_project,依赖于这个shared_package,需要部署到AWS Elastic Beanstalk(EB)。我们的环境使用最新的";Python on Amazon Linux 2";平台,我们使用pipenv作为包管理器。

由于各种原因,我们最方便的方法是直接从我们的在线git存储库安装shared_package,如这里对pipenv和这里对pip所述。我们的dependent_projectPipfile看起来像这样:

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
shared_package = {git = "ssh://bitbucket.org/our_username/shared_package.git", editable = true, ref = "2021.0"}
[dev-packages]
awsebcli = "*"
[requires]
python_version = "3.8"

这在我们的本地开发系统上运行良好,但当将dependent_project部署到Elastic Beanstalk时,pipenv安装失败,出现:Permission denied (publickey)

这就引出了一个问题:

如何使用Amazon Linux 2平台挂钩配置Elastic Beanstalk环境,以便pipenv能够通过SSH成功安装来自私人在线git repo的包

以下讨论中可以找到一些谜题,但这些都没有使用AmazonLinux2平台挂钩:

  • 使用AWS Elastic Beanstalk和Ruby容器设置私有Github访问
  • 在Elastic Beanstalk上设置github私有回购访问的SSH密钥
  • 处理node.js私有模块依赖关系的推荐方法是什么
  • BitBucket:主机密钥验证失败
  • 授予S3对Elastic Beanstalk实例的访问权限
  • 如何使用Amazon AWS Elastic Beanstalk部署私有python pip依赖关系
  • AWS Elastic Beanstalk中的Python:私有包依赖关系

摘要

假设我们已经定义了以下Elastic Beanstalk环境属性,并且bitbucket公钥文件和我们的私钥文件都已上传到指定的S3 bucket:

S3_BUCKET_NAME="my_bucket"
REPO_HOST_NAME="bitbucket.org"
REPO_HOST_PUBLIC_KEY_NAME="bitbucket_public_key"
REPO_PRIVATE_KEY_NAME="my_private_key"

然后可以使用.platform/hooks/prebuild:中的这个钩子来完成配置

#!/bin/bash
# git is required to install our python packages directly from bitbucket
yum -y install git
# file paths (platform hooks are executed as root)
SSH_KNOWN_HOSTS_FILE="/root/.ssh/known_hosts"
SSH_CONFIG_FILE="/root/.ssh/config"
PRIVATE_KEY_FILE="/root/.ssh/$REPO_PRIVATE_KEY_NAME"
# remove any existing (stale) keys for our host from the known_hosts file
[ -f $SSH_KNOWN_HOSTS_FILE ] && ssh-keygen -R $REPO_HOST_NAME
# read the (fresh) host key from S3 file and append to known_hosts file
aws s3 cp "s3://$S3_BUCKET_NAME/$REPO_HOST_PUBLIC_KEY_NAME" - >> $SSH_KNOWN_HOSTS_FILE
# copy our private key from S3 to our instance
aws s3 cp "s3://$S3_BUCKET_NAME/$REPO_PRIVATE_KEY_NAME" $PRIVATE_KEY_FILE
# create an ssh config file to point to the private key file
tee $SSH_CONFIG_FILE <<HERE
Host $REPO_HOST_NAME
User git
Hostname $REPO_HOST_NAME
IdentityFile $PRIVATE_KEY_FILE
HERE
# file permissions must be restricted
chmod 600 $SSH_CONFIG_FILE
chmod 600 $PRIVATE_KEY_FILE

请注意,此文件需要执行权限(chmod +x <file path>)。

详细说明

请继续阅读,了解详细的原理。

Git

要访问git存储库,我们的Elastic Beanstalk环境需要安装git。这可以在使用yum的平台挂钩中完成(-y对每个问题都假设"是"):

yum -y install git

SSH密钥

为了在我们的Elastic Beanstalk(EB)实例和例如bitbucket存储库之间建立SSH连接,我们需要三个SSH密钥:

  • bitbucket.org的公共密钥,用于验证我们是否正在连接到受信任的主机。

    为了获得bitbucket.org的公钥,我们可以使用ssh-keyscan以适合known_hosts的格式。为了安全起见,我们应该使用";"可信";来源在我们的情况下,我们能做的最好的事情是将公钥指纹与";官方的";一个发布在bitbucket(或github)网站上。指纹可以使用ssh-keygen从公钥计算,例如

    ssh-keyscan -t rsa bitbucket.org | ssh-keygen -lf -
    
  • 我们存储库的私钥公钥

    可以使用ssh-keygen生成由私钥和公钥组成的密钥对。私钥必须保密,公钥必须复制到";访问密钥";对于bitbucket存储库,如bitbucket文档中所述。请注意,创建一个没有密码短语的密钥对最方便,否则我们的脚本也需要处理密码短语。

在AWS上存储密钥

部署期间,EB环境中需要提供公共比特桶主机密钥和我们的私有回购密钥。私有密钥是秘密的,因此它不应存储在源代码中,也不应以其他方式进行版本控制。

最方便的选择是将键值存储为EB环境属性(即环境变量),因为这些属性在部署过程中很容易获得。原则上,这可以完成,例如使用base64编码将多行私钥存储在单行环境属性中。然而,所有EB环境属性键和值组合的总大小仅限于4096字节,这基本上排除了此选项。

另一种选择是将密钥文件存储在AWS S3上的安全私有存储桶中。该文档描述了如何设置IAM角色,该角色为EC2实例授予对S3存储桶的访问权限。文档确实提供了一个配置示例,但它使用.ebextensions,不适用于.platform挂钩。

简而言之,我们可以创建一个具有默认设置的基本S3存储桶("阻止公共访问"已启用,没有自定义权限),并将SSH密钥文件上传到该存储桶。然后,使用AWS IAM web控制台,选择aws-elasticbeanstalk-ec2-role(或者,最好创建一个自定义角色),并附加AmazonS3ReadOnlyAccess策略。

在部署到Elastic Beanstalk的过程中,我们可以使用.platform挂钩,使用aws-cli将S3 bucket中的密钥文件下载到EC2实例。

为了测试EC2和S3之间的连接,我们可以使用eb-ssh连接到EC2实例,然后使用aws s3 ls s3://<bucket name>列出bucket内容。

更新已知主机

为了表明bitbucket.org是一个受信任的主机,需要将其公钥添加到我们实例上的known_hosts文件中。在我们的平台挂钩脚本中,我们删除主机的任何现有公钥,以防它们过时,并用S3上文件中的当前密钥替换它们:

SSH_KNOWN_HOSTS_FILE="/root/.ssh/known_hosts"
[ -f $SSH_KNOWN_HOSTS_FILE ] && ssh-keygen -R $REPO_HOST_NAME
aws s3 cp "s3://$S3_BUCKET_NAME/$REPO_HOST_PUBLIC_KEY_NAME" - >> $SSH_KNOWN_HOSTS_FILE

指定私钥

私钥可以从S3下载如下,我们需要限制文件权限:

PRIVATE_KEY_FILE="/root/.ssh/$REPO_PRIVATE_KEY_NAME"
aws s3 cp "s3://$S3_BUCKET_NAME/$REPO_PRIVATE_KEY_NAME" $PRIVATE_KEY_FILE
chmod 600 $PRIVATE_KEY_FILE

还需要一个SSH配置文件来指向私钥:

tee $SSH_CONFIG_FILE <<HERE
Host $REPO_HOST_NAME
User git
Hostname $REPO_HOST_NAME
IdentityFile $PRIVATE_KEY_FILE
HERE
chmod 600 $SSH_CONFIG_FILE

同样,必须限制文件权限。

最后的脚本显示在顶部的摘要中。该脚本可以例如作为.platform/hooks/prebuild/01_configure_bitbucket_ssh.sh存储在项目文件夹中。

挂钩和配置挂钩

请注意,AmazonLinux2使用.platform/hooks进行正常部署,使用.platform/confighooks进行配置部署。通常,在这两种情况下都需要使用相同的脚本。为了防止代码重复,我们的.platform/confighooks/prebuild/01_configure_bitbucket_ssh.sh可能看起来像这样:

#!/bin/bash
source "/var/app/current/.platform/hooks/prebuild/01_configure_bitbucket_ssh.sh"

请注意,应用程序代码最终会出现在实例的/var/app/current中。

相关内容

  • 没有找到相关文章

最新更新