Cloud build do the following:
My issue is the following:
As I'm running my tests on build time, I need my MONGODB_URI
secret on build time, but I've read that using --build-arg
is not safe to expose secrets.
I could run npm install
and npm run test
in Cloud Build container, but it would make build time longer as I'll have to run npm install two times.
Is there a way I can run only once npm install without having to expose secrets ?
Dockerfile
FROM node:16
COPY . ./
WORKDIR /
RUN npm install
ARG env
ARG mongodb_uri
ENV ENVIRONMENT=$env
ENV DB_REMOTE_PROD=$mongodb_uri
RUN npm run test
RUN npm run build
CMD ["node", "./build/index.js"]
And my cloudbuild.yaml config:
steps:
- name: gcr.io/cloud-builders/docker
args:
- '-c'
- >-
docker build --no-cache -t
$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA
--build-arg ENVIRONMENT=staging --build-arg mongodb_uri=$$MONGODB_URI -f
Dockerfile .
id: Build
entrypoint: bash
secretEnv:
- MONGODB_URI
- name: gcr.io/cloud-builders/docker
args:
- push
- '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
id: Push
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
args:
- '-c'
- >-
gcloud run services update $_SERVICE_NAME --platform=managed
--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA
--labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID
--region=$_DEPLOY_REGION --update-env-vars=ENVIRONMENT=staging
--update-env-vars=DB_REMOTE_PROD=$$MONGODB_URI --quiet
id: Deploy
entrypoint: bash
secretEnv:
- MONGODB_URI
images:
- '$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA'
options:
substitutionOption: ALLOW_LOOSE
logging: CLOUD_LOGGING_ONLY
substitutions:
_TRIGGER_ID: 44b16efe-0219-41af-b32b-9b98438728c3
_GCR_HOSTNAME: eu.gcr.io
_PLATFORM: managed
_SERVICE_NAME: app-staging
_DEPLOY_REGION: europe-southwest1
availableSecrets:
secretManager:
- versionName: projects/PROJECT_ID/secrets/mongodb_app_staging/versions/1
env: MONGODB_URI
With my method, the secret is exposed not only in the container since I pass it as build-args, but it is also exposed to all users with access to cloud run...
Your container build step is not so bad. You provide your secrets to your container, but it is not visible. It's only reference.
You can hardly do better. A solution could be to perform the secret access directly inside the Dockerfile, but I'm not sure that the "security gain" worth the Dockerfile increased complexity. (If you want more details, let me know, I will be able to share sample)
About Cloud Run, you are totally true: exposing secret in plain text in environment variable is totally not acceptable.
For that, you can use the Cloud Run - Secret Manager integration. Instead of doing this
gcloud run services update $_SERVICE_NAME --platform=managed
--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA
--labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID
--region=$_DEPLOY_REGION --update-env-vars=ENVIRONMENT=staging
--update-env-vars=DB_REMOTE_PROD=$$MONGODB_URI --quiet
You can do that (and you now longer need to set the secret as env var of your Cloud Build step)
gcloud run services update $_SERVICE_NAME --platform=managed
--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_SERVICE_NAME:$COMMIT_SHA
--labels=managed-by=gcp-cloud-build-deploy-cloud-run,commit-sha=$COMMIT_SHA,gcb-build-id=$BUILD_ID,gcb-trigger-id=$_TRIGGER_ID
--region=$_DEPLOY_REGION --update-env-vars=ENVIRONMENT=staging
--update-secrets=DB_REMOTE_PROD=mongodb_app_staging:1 --quiet