用例
[对于部署到 Cloud Run 的 docker 容器],在构建时运行单元测试,其中一些需要 secret 和某种级别的 google 身份验证。单元测试可能需要身份验证才能与云存储等 Google 服务进行交互,或者从 Google KMS 检索 key 以测试与其他经过身份验证的 API 的交互。根据我对gcloud authentication的理解,在构建时提供凭据的唯一方法是通过服务帐户的凭据 json 文件(而当触发部署的服务时,ADC 可以使用 Cloud Run 提供的服务帐户)。 p>
当前方法
假设我们已在本地为我们的服务帐户生成了凭据文件
- 检查构建是在本地启动还是由 github 触发器启动。如果构建是由 github 触发器触发的,则仅运行不需要身份验证的单元测试,因为在这种情况下,我还没有找到在构建时获取凭据的方法。
- [仅当这是本地触发的构建时才继续]。通过构建参数将凭证文件内容作为 base64 编码字符串复制到 dockerfile
- 通过解码 Base64 编码的构建参数,在构建期间创建临时凭证文件
- 使用该凭据文件运行所有单元测试
- 删除凭据文件,因为已部署的容器中不需要该文件
当前实现
[严重且可能不安全的代码触发警告]
$cloud-build-local --config=build_config/cloudbuild_manual.json \
--dryrun=false \
--push \
--substitutions=\
_JSON_CONTENTS="$$(cat $(CREDENTIALS_PATH) | base64)",\
_CONTAINER_ID="$(CONTAINER_ID)" \
.
cloudbuild_manual.json
{
"name": "gcr.io/cloud-builders/docker",
"args": [
"build",
"--build-arg",
"JSON_CONTENTS=${_JSON_CONTENTS}",
"--build-arg",
"PROJECT_ID=${PROJECT_ID}",
"--build-arg",
"RUN_AUTHENTICATED_TESTS=true",
"-t",
"gcr.io/${PROJECT_ID}/${_CONTAINER_ID}",
"."
],
"env":[],
"timeout": "500s"
}
...
Dockerfile
ARG RUN_AUTHENTICATED_TESTS=false
ENV CREDENTIALS_TEMP_LOCATION credentials_temp.json
ARG JSON_CONTENTS
...
RUN if [ "$RUN_AUTHENTICATED_TESTS" = "true" ] ; then \
echo "${JSON_CONTENTS}" | base64 -d > $CREDENTIALS_TEMP_LOCATION && \
PYTHONPATH=$PYTHONPATH:`pwd`/ pytest -v --run-auth && \
rm $CREDENTIALS_TEMP_LOCATION ; \
else \
PYTHONPATH=$PYTHONPATH:`pwd`/ pytest -v ; \
fi;
...
这种方法的问题
- 这让我内心感到恶心
- 未提供可通过 github 触发器进行持续部署的解决方案
- 可能不安全?
可能的解决方案
使用vcrpy或类似的数据模拟库来拦截所有单元测试的交互并将其替换为记录的版本,从而消除在构建时进行任何类型的身份验证的需要。确保从记录中审查所有 token 和 key 以确保安全(避免在 git 存储库中以明文形式存储 API key )。
我很想听听您对我当前的方法、替代方法以及您可能拥有的任何其他解决方案的想法。请随意谈论我的垃圾解决方案:)
最佳答案
没有什么是神奇的。如果您的 Dockerbuild 需要身份验证参数,您必须提供它。环境变量或构建参数是将这些数据传递到 docker build 进程的好方法。您还可以通过重用文件系统中存在的文件来避免这种情况。
secret 存储和恢复似乎是一个问题。我的建议是将其存储到 Secret Manager 。这是保守 secret 的最佳场所。
现在在您的cloudbuild.yaml
文件中,您必须一步步获取 secret ,然后在docker build
阶段传递它
step:
- name: gcr.io/cloud-builders/gcloud
entrypoint: bash
args:
- "-c"
- |
gcloud beta secrets versions access --secret=mySecretName latest > /workspace/mySecret.txt
- name: gcr.io/cloud-builders/docker
args: [
"build",
"--build-arg",
"PROJECT_ID=${PROJECT_ID}",
"--build-arg",
"RUN_AUTHENTICATED_TESTS=true",
"-t",
"gcr.io/${PROJECT_ID}/${_CONTAINER_ID}",
"."
],
timeout: "500s"
你的 Dockerfile
...
ARG RUN_AUTHENTICATED_TESTS=false
ENV CREDENTIALS_TEMP_LOCATION credentials_temp.json
COPY mySecret.txt $CREDENTIALS_TEMP_LOCATION
...
我的观点:永远不要持有凭证更安全。让它们安全存放。 secret 经理是一个很好的地方!
关于google-cloud-platform - 在构建时处理 secret ,以便对部署到 Cloud Run 的容器进行单元和集成测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62732900/