构建并上载到本地Python存储库而无需将凭据写入磁盘

时间:2017-11-14 18:01:36

标签: python artifactory setuptools

我已经建立了一个Python构建管道,其中一个Jfrog Artifactory Python存储库为我们的内部包提供服务。

管道使用此存储库来解析内部依赖关系并上传构建工件。

目前使用python setup.py bdist_wheel sdist upload -r local完成此操作。此命令实际上要求凭据在磁盘上两次;一次通过〜/ .pydistutils.cfg解析本地依赖:

[easy_install]
index_url=https://username:password@artifactory/api/repo/path/simple

...再次在〜/ .pypirc中上传构建包:

[distutils]
index-servers = local

[local]
repository: https://artifactory/api/repo/path
username: build_agent
password: ****

出于安全考虑,我希望用户名和密码永远不会触及磁盘。我们已经有了一种从(Hashicorp)Vault向构建环境注入秘密的安全方法,我想利用它来获取Artifactory凭据。

但是,虽然我可以设置PIP_INDEX_URL来安装带有pip的软件包,但是我看不到setuptools的等价物。如果未定义这些文件,命令python setup.py sdist将导致堆栈跟踪以下错误:

distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse('local-package==0.0.3')

显然,它正在尝试解决对公共pypi的本地依赖,由于多种原因(本地存储代理pypi,因此我们不应该读取公共pypi以防止劫持)这是不可取的。

基本上我的问题是; 如何使用环境变量中的凭据(而不是〜/ .pypirc或〜/ .pydistutils.cfg?)构建和上传本地存储库中具有依赖关系的python包到本地存储库?强>

其他背景

原始实现在构建代理AMI中烘焙了.pypirc和.pydistutils.cfg,它是使用Packer构建的。

问题在于,存储库的用户名和密码基本上可以由任何有权访问AWS账户的人以纯文本阅读,并且能够使用该图像下载或创建新实例。

这很简单,只需添加一个构建步骤,在开始构建之前设置pypirc!我想避免这种方法,因为它在创建全局运行时构建依赖性的意义上是脆弱的。将来,有人可以设置一个工作,假设配置文件已经创建,而不是自己创建,并且它几乎总是有效,因为另一个工作已经先运行。我无法在每次构建后删除该文件,因为可能存在需要文件存在的并发构建。

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方案,但它并不是特别漂亮。

第一个问题是setup_requires。因为它在过程中如此早地调用easy_install,所以很难覆盖;甚至创建一个Distribution子类并覆盖fetch_egg方法也没有帮助。我现在解决的解决方法是包装设置方法并通过pip预先安装它们(设置PIP_INDEX_URL):

from setuptools import setup

def _setup(**kwargs):
    requires = kwargs.get('setup_requires') or []

    for req in requires:
        pip.main(['install', req])

    return setup(**kwargs)


_setup(
    name='mypackage',
    ...
)

只有在setup_requires中指定本地依赖关系的包时才需要这样,并且python setup.py install仍然存在。由于pip在tox(deps = .[test]部分中的[testenv])中安装并且从不使用setup.py进行安装,因此破坏的安装命令不是问题。

第二个问题是上传。我没有使用setup.py上传进行上传,而是将此任务转移到twine。最新版本的twine从环境中读取TWINE_USERNAME,TWINE_PASSWORD和TWINE_REPOSITORY_URL(如果它们不在传统的配置文件中)。

无论如何,我希望找到一个更优雅的解决方案来解决第一个问题,特别是那个没有让setup.py安装破坏的问题,但是现在这样做了。