-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pass OIDC config from .env to Backend and Frontend #458
Conversation
docker-compose.yml
Outdated
@@ -85,6 +89,7 @@ services: | |||
- SENTRY_ORG_SUBDOMAIN=${SENTRY_ORG_SUBDOMAIN:-o130137} | |||
- SENTRY_KEY=${SENTRY_KEY:-3cf75f54983e473da6bd07daddf0d2ee} | |||
- SENTRY_PROJECT=${SENTRY_PROJECT:-1298632} | |||
- OIDC_ENABLED=${OIDC_ENABLED:-false} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Vue build has access to environment variables via process.env
, so I'm thinking that we can set oidcEnabled
to process.env.OIDC_ENABLED
in src/config.js. I don't remember the details of that mechanism (I'll look more into it later this week), I think we may need to add a Vue-specific prefix to the name of the environment variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked, and it looks like the build mostly just has access to environment variables prefixed with VUE_APP_
: https://cli.vuejs.org/guide/mode-and-env.html#environment-variables. I think I'm going to keep it named OIDC_ENABLED
in docker-compose.yml, then add the prefix just when calling npm run build
. It looks like the VUE_APP_
prefix may need to change to VITE_
once we move to Vite (getodk/central-frontend#671).
Also, I'm not sure, but for nginx
, I think OIDC_ENABLED
needs to be specified in docker-compose.yml under build.args
rather than environment
in order for it to make its way to build-frontend.sh. The variable journeys through a couple of layers before eventually reaching npm build
.
ccf6ca8
to
28e93d7
Compare
28e93d7
to
f666acc
Compare
nginx.dockerfile
Outdated
@@ -1,8 +1,9 @@ | |||
ARG OIDC_ENABLED |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most examples of ARG
that I've seen have ARG
after FROM
. But service.dockerfile has ARG
before FROM
. Maybe because there are two FROM
s? Things seem to be working here with ARG
before FROM
, but I could look more into this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a strange use of ARG
, or perhaps a strange position for it in the dockerfile. Will setting it here mean every single layer in the dockerfile needs rebuilding when OIDC_ENABLED
is toggled?
Is it even necessary to set this in the dockerfile at all? Presumably RUN files/prebuild/build-frontend.sh
can't pick up standard env vars set in docker-compose.yml
(?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps a strange position for it in the dockerfile
I've moved ARG
to after the first FROM
. Based on how I understand the docs, I think that's what's needed here.
Will setting it here mean every single layer in the dockerfile needs rebuilding when
OIDC_ENABLED
is toggled?
This question makes me wonder, should I move ARG
even further down, to right before RUN files/prebuild/build-frontend.sh
? I don't think what comes before build-frontend.sh takes much time, so I doubt there'd be a big difference. But to be explicit, if an OIDC_*
config is changed, the Vue build will need to be rerun.
Presumably
RUN files/prebuild/build-frontend.sh
can't pick up standard env vars set indocker-compose.yml
(?)
That's my impression from reading some of the docs, but I'm definitely no Docker expert. I tried it out in a couple of commits here, and it does look like variables set in environment
aren't available in the build. From the build for 735cbe7:
$OIDC_DISCOVERY_URL in the Dockerfile: [blank]
...
$OIDC_DISCOVERY_URL in build-frontend.sh: [blank]
From the build for 8171f6c (using build.args
instead):
$OIDC_DISCOVERY_URL in the Dockerfile: [foobar]
...
$OIDC_DISCOVERY_URL in build-frontend.sh: [foobar]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like it matters where the ARG
is declared:
Impact on build caching
ARG
variables are not persisted into the built image asENV
variables are. However,ARG
variables do impact the build cache in similar ways. If a Dockerfile defines anARG
variable whose value is different from a previous build, then a “cache miss” occurs upon its first usage, not its definition. In particular, all RUN instructions following anARG
instruction use theARG
variable implicitly (as an environment variable), thus can cause a cache miss. All predefinedARG
variables are exempt from caching unless there is a matchingARG
statement in the Dockerfile.
-https://docs.docker.com/engine/reference/builder/#impact-on-build-caching
I think declaring directly before use is probably better:
- while build times may not be affected much, the number of local images will be, and associated disk usage
- it may make it clearer to future maintainers where the
ARG
is used
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done! I've moved ARG
to right before build-frontend.sh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approved if we're happy with current secret management.
a79a88b
to
6a66762
Compare
I think what this PR does is consistent with what we've done in the past. Feel free to file an issue though if you think we should rethink that approach! |
61b3afc
to
668ee78
Compare
668ee78
to
735cbe7
Compare
OK, I'm feeling more confident about this approach! @alxndrsn, would you mind taking another look? |
nginx.dockerfile
Outdated
@@ -1,8 +1,12 @@ | |||
FROM node:18.17 as intermediate | |||
ARG OIDC_DISCOVERY_URL |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to note this warning I'm seeing about ARG
:
It is not recommended to use build-time variables for passing secrets like GitHub keys, user credentials etc. Build-time variable values are visible to any user of the image with the
docker history
command.
I don't think this is a particular problem for us, because anyone who could run docker history
on the machine would also be able to read the .env file. Passing this information via build.args
doesn't seem riskier than passing it via environment
. However, I wanted to mention the warning in case I'm misunderstanding something about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, build-frontend.sh derives VUE_APP_OIDC_ENABLED
from the other three OIDC_*
variables. It'd be nice if we could derive that value somewhere prior to the Dockerfile, then pass only that value to the Dockerfile as an ARG
. However, I don't know of an easy way to do that with our current setup. And again, my understanding is that this approach isn't a particular risk for us.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@alxndrsn and I discussed this earlier today. Instead all three OIDC_*
variables being passed to nginx.dockerfile, now only OIDC_DISCOVERY_URL
will be passed. Unlike OIDC_CLIENT_SECRET
, OIDC_DISCOVERY_URL
isn't sensitive, so there shouldn't be an issue that it is passed via ARG
. build-frontend.sh will derive VUE_APP_OIDC_ENABLED
based only on the presence of OIDC_DISCOVERY_URL
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if derived from OIDC_DISCOVERY_URL
, I think it would still be helpful to call this OIDC_ENABLED
or similar in the frontend image, as that is what it's used for. I think seeing OIDC_DISCOVERY_URL
in the frontend would raise questions about why it's being passed there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OIDC_DISCOVERY_URL
won't be visible in the JS that's built, just VUE_APP_OIDC_ENABLED
. Is there somewhere other than the JS that you're thinking about? I think we can assume that anyone examining the source will be able to determine why the variable is passed to nginx.dockerfile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alex and I chatted about this earlier today. We decided to reintroduce a separate OIDC_ENABLED
variable so that we don't need to pass the discovery/issuer URL to the Frontend build. The user will specify the OIDC_ENABLED
variable: it's not derived from the other variables. I've made this change in a commit I just pushed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good to me
@@ -4,7 +4,7 @@ echo "generating local service configuration.." | |||
|
|||
ENKETO_API_KEY=$(cat /etc/secrets/enketo-api-key) \ | |||
BASE_URL=$( [ "${HTTPS_PORT}" = 443 ] && echo https://"${DOMAIN}" || echo https://"${DOMAIN}":"${HTTPS_PORT}" ) \ | |||
envsubst '$DOMAIN $BASE_URL $SYSADMIN_EMAIL $ENKETO_API_KEY $DB_HOST $DB_USER $DB_PASSWORD $DB_NAME $DB_SSL $EMAIL_FROM $EMAIL_HOST $EMAIL_PORT $EMAIL_SECURE $EMAIL_IGNORE_TLS $EMAIL_USER $EMAIL_PASSWORD $SENTRY_ORG_SUBDOMAIN $SENTRY_KEY $SENTRY_PROJECT' \ | |||
envsubst '$DOMAIN $BASE_URL $SYSADMIN_EMAIL $ENKETO_API_KEY $DB_HOST $DB_USER $DB_PASSWORD $DB_NAME $DB_SSL $EMAIL_FROM $EMAIL_HOST $EMAIL_PORT $EMAIL_SECURE $EMAIL_IGNORE_TLS $EMAIL_USER $EMAIL_PASSWORD $OIDC_ENABLED $OIDC_ISSUER_URL $OIDC_CLIENT_ID $OIDC_CLIENT_SECRET $SENTRY_ORG_SUBDOMAIN $SENTRY_KEY $SENTRY_PROJECT' \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create an issue about this #473
I'm going to go ahead and merge! In addition to @sadiqkhoja's approval, the final version of the code is very similar to the version that @alxndrsn approved. @alxndrsn, let me know if you have additional thoughts about anything here! |
I'm pushing this PR mostly in order to start a conversation about where/how Central users should configure SSO and how that config will be passed through to Backend and Frontend.
Related to the issue for SSO, #449.
What has been done to verify that this works as intended?
I haven't tested this yet, but I wanted to get initial thoughts from @alxndrsn.
Why is this the best possible solution? Were any other approaches considered?
This is similar to how we pass other config to Backend. We haven't had to pass config to Frontend before, so that part is new.
Before submitting this PR, please make sure you have: