Heroku:private repos中的Python依赖项,无需存储我的密码 问题

Heroku:private repos中的Python依赖项,无需存储我的密码 问题,python,heroku,github,Python,Heroku,Github,我的问题就像和。也就是说,我有一个私有repo,我需要在我的Heroku应用程序中安装一个Python依赖项。Heroku自己给出的结论是 -e git+https://username:password@github.com/kennethreitz/requests.git@v0.10.0#egg=requests 在您的requirements.txt文件中 我的安全需要阻止我将密码存储在repo中。(我也不想将依赖关系放在我的应用程序的repo中;它们是独立的软件,需要在独立的repo

我的问题就像和。也就是说,我有一个私有repo,我需要在我的Heroku应用程序中安装一个Python依赖项。Heroku自己给出的结论是

-e git+https://username:password@github.com/kennethreitz/requests.git@v0.10.0#egg=requests
在您的
requirements.txt
文件中

我的安全需要阻止我将密码存储在repo中。(我也不想将依赖关系放在我的应用程序的repo中;它们是独立的软件,需要在独立的repo中。)我唯一可以向Heroku提供密码(或者最好是GitHub OAuth令牌或部署密钥)的地方,是在一个环境变量中,如

heroku config:add GITHUB_OAUTH_TOKEN=12312312312313
尝试的解决方案 我可以在应用程序的repo中使用自定义的
.profile
,但是每次进程(web、worker等)重新启动时,我都会下载并安装依赖项

这样就可以使用定制的buildpack和在buildpack编译之前公开my
heroku config
环境的。我试了一下。其思想是Buildpack Multi是主要的Buildpack,使用我的应用程序repo中的
.buildpacks
文件,它首先下载普通的Heroku Python Buildpack,然后下载我的自定义Buildpack

问题是,即使在Buildpack Multi成功运行Python Buildpack之后,Buildpack Multi运行一次后,我的Buildpack也会被发送到我的Buildpack。因此,定制构建包完全失败了。(在我的测试中,
GITHUB\u OAUTH\u令牌
环境变量已正确地公开给构建包。)

我唯一可以考虑尝试的另一件事是制作我自己的Python buildpack分支,当它安装了
requirements.txt
中的所有内容,甚至直接重写
requirements.txt
时安装我的依赖项。这两个似乎都是解决我认为是一个非常普遍的问题的非常沉重的解决方案

更新:当前解决方案 我的自定义buildpack(如上链接)现在下载并将我的封闭源代码依赖项(“foo”)保存到geos buildpack使用的供应商目录中。我向我的应用程序提交了foo本身在我的应用程序的
requirements.txt
中的依赖项。因此,Pip通过我的应用程序的
requirements.txt
安装foo的依赖项,构建包将foo的供应商副本添加到我的应用程序环境的
PYTHONPATH
(因此foo的
setup.py安装永不会运行)

这种方法的最大问题是将我的构建包(公认写得很糟糕)与我的应用程序耦合在一起。第二个问题是,我的应用程序的
requirements.txt
应该将foo列为依赖项,并将foo的依赖项留给foo来确定。最后,如果我忘记设置GITHUB_OAUTH_令牌环境变量(或者,如果令牌过期且环境变量仍然存在但不再有效,则产生更不有用的错误反馈),那么在六个月后,如果我忘记了我是如何完成这一切的,那么就没有一个好的方法给我自己一条错误消息

呼救
我遗漏了什么(可能是显而易见的)?您是如何在应用程序中解决此问题的?关于如何让我的构建包工作,或者希望有一个更简单的解决方案,有什么建议吗?

您可以使用预编译步骤来运行类似M4的程序,对requirements.txt进行替换,以从环境变量中输入密码

我创建了一个buildpack,使用存储为环境变量的自定义ssh密钥来解决这个问题。由于buildpack与技术无关,因此可以使用任何工具(如composer for php、bundler for ruby、npm for javascript等)下载依赖项:

  • 将构建包添加到您的应用程序:

    $ heroku buildpacks:add --index 1 https://github.com/simon0191/custom-ssh-key-buildpack
    
  • 生成一个新的SSH密钥(假设您将其命名为deploy_key)

  • 将公钥添加到您的私有存储库帐户。例如:

    • Github:

    • 比特桶:

  • 将私钥编码为base64字符串,并将其添加为heroku应用程序的
    CUSTOM\u SSH\u key
    环境变量

  • # MacOS
    $ heroku config:set CUSTOM_SSH_KEY=$(base64 --input ~/.ssh/deploy_key) CUSTOM_SSH_KEY_HOSTS=bitbucket.org,github.com
    # Ubuntu
    $ heroku config:set CUSTOM_SSH_KEY=$(base64 ~/.ssh/deploy_key) CUSTOM_SSH_KEY_HOSTS=bitbucket.org,github.com
    
  • 创建一个以逗号分隔的主机列表,列出应使用ssh密钥的主机,并将其添加为heroku应用程序的
    自定义_ssh_key_hosts
    环境变量

    # MacOS
    $ heroku config:set CUSTOM_SSH_KEY=$(base64 --input ~/.ssh/deploy_key) CUSTOM_SSH_KEY_HOSTS=bitbucket.org,github.com
    # Ubuntu
    $ heroku config:set CUSTOM_SSH_KEY=$(base64 ~/.ssh/deploy_key) CUSTOM_SSH_KEY_HOSTS=bitbucket.org,github.com
    
  • 部署你的应用并享受:)

  • 我也面临同样的问题。和您一样,我也很惊讶找到关于如何安装私有依赖关系(无论使用何种语言和服务)的好文档是多么困难

    因为这不是服务提供商主要关心的问题,所以我现在尝试一种系统方法,尽可能少地依赖于特性。我尝试为以下每个步骤找到更简单的解决方案:

    • 使用安全通道将凭据传递到生成环境。对于python,使用包含SSH密钥的环境变量作为base64字符串。对于js,与npm令牌相同
    • 配置生成过程以使用这些凭据。在最好的情况下,它涉及配置ssh以使用部署密钥。否则,它可以像克隆依赖项一样基本,以备将来使用。对于python和heroku的特定情况,可以使用钩子“pre_compile”
    我在这里详细介绍了我未来自我的过程:


    我需要给一个私人的依赖。持续集成或部署时可能会发生这种情况

    这里我们使用python和github,使用CircleCI和Heroku服务。然而,这些原则适用于所有地方

    什么是部署密钥? 看

    有4种方法可以授予对私有依赖项的访问权,但对于不需要太多依赖项的项目(在这种情况下,更喜欢机器用户),部署密钥在安全性和易用性方面是一个很好的折衷方案。在任何情况下,都不要使用开发人员帐户或oauth令牌的用户名/密码,因为它们不提供权限限制

    创建部署密钥:

    ssh-keygen -t rsa -b 4096 -C "myself@my_company.com"
    
    将公共部分交给gihub

    将私有部分提供给需要访问的服务。见下文

    总体战略 W
    echo $DEPLOY_KEY_PRIVATE | base64 --decode > ~/.ssh/deploy-key
    chmod 400 ~/.ssh/deploy-key
    echo $DEPLOY_KEY_PUBLIC | base64 --decode > ~/.ssh/deploy-key.pub
    ssh-add ~/.ssh/deploy-key
    
    # Run this to check which private key is used. If the checkout key is used,
    # github replies "Hi my_org/my_package". If the deploy key is used as wished,
    # github replies "Hi my_org/my_dependency".
    #ssh -i ~/.ssh/deploy-key -T git@github.com || true
    
    # Now pip connects to git+ssh using the deploy key
    export GIT_SSH_COMMAND="ssh -i ~/.ssh/deploy-key"
    
    pip install -r requirements.txt
    
    # The purpose of this file is to install the private dependency *before*
    # setup.py is run.
    
    # Be sure ssh is configured to use a ssh key with read permission to the repo.
    git+ssh://git@github.com/my_org/my_dependency@1.0.10
    
    # Run setup.py. The private dependency is already installed with the good
    # version so pip doesn't try to fetch it from PyPI.
    --editable .
    
    from distutils.core import setup
    
    setup(
        name='my_package',
        version='1.0',
        packages=[
            'my_package',
        ],
        install_requires=[
            # Beware, the following package is a private dependency.
            # Python provides several way to install private dependencies, none
            # are really satisfactory.
            # 1. Use dependency_links / --process-dependency-links. Good luck with
            #    that!
            # 2. Maintain a private package repository. Good luck with that!
            # 3. Install the private dependency separately before setup.py is run.
            #    This is now the prefered way. Be sure that ssh is properly
            #    configured to use a ssh key with read permission to the github repo
            #    of the private dependency, then run:
            #    `pip install -r requirements.txt`
            'my_dependency==1.0.10',
            ... # my normal dependencies
            'unidecode==1.0.22',
            'uwsgi==2.0.15',
            'nose==1.3.7', # tests
            'flake8==3.5.0', # style
        ],
    )
    
    # This script configures ssh on Heroku to use the deploy key.
    # This is needed to install private dependencies.
    #
    # Note that this does not work with Heroku review apps. Indeed review apps can
    # inherits env variables from their parents, but they access their values after
    # the build. You would need a way to pass the ssh key to this script another
    # way.
    #
    # See also
    # * https://stackoverflow.com/questions/21297755/heroku-python-dependencies-in-private-repos-without-storing-my-password#
    # * https://github.com/bjeanes/ssh-private-key-buildpack
    
    # Ensure we have an ssh folder
    if [ ! -d ~/.ssh ]; then
      mkdir -p ~/.ssh
      chmod 700 ~/.ssh
    fi
    
    # Create the key files
    cat $ENV_DIR/DEPLOY_KEY | base64 --decode > ~/.ssh/deploy-key
    chmod 400 ~/.ssh/deploy-key
    cat $ENV_DIR/DEPLOY_KEY | base64 --decode > ~/.ssh/deploy-key.pub
    #ssh-add ~/.ssh/deploy-key
    
    # If you want to disable host verification, you could use that.
    #ssh -oStrictHostKeyChecking=no -T git@github.com 2>&1
    
    # Run that if you want to check that ssh uses the correct key.
    #ssh -i ~/.ssh/deploy-key -T git@github.com || true
    
    # Configure ssh to use the correct deploy key when connecting to github.
    # Disables host verification.
    echo -e "Host github.com\n"\
            "  IdentityFile ~/.ssh/deploy-key\n"\
            "  IdentitiesOnly yes\n"\
            "  UserKnownHostsFile=/dev/null\n"\
            "  StrictHostKeyChecking no"\
            >> ~/.ssh/config
    
    # Unfortunately this does not seem to work.
    #export GIT_SSH_COMMAND="ssh -i ~/.ssh/deploy-key"
    
    # The vanilla python buildpack can now install all the dependencies in
    # requirement.txt
    
        # Set Pip env vars
        # This reads certain environment variables set on the Heroku app config
        # and makes them accessible to the pip install process.
        #
        # PIP_EXTRA_INDEX_URL allows for an alternate pypi URL to be used.
        if [[ -r "$ENV_DIR/PIP_EXTRA_INDEX_URL" ]]; then
            PIP_EXTRA_INDEX_URL="$(cat "$ENV_DIR/PIP_EXTRA_INDEX_URL")"
            export PIP_EXTRA_INDEX_URL
            mcount "buildvar.PIP_EXTRA_INDEX_URL"
        fi