Skip to content
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

feat: Add gomplate to the docker image #1893

Merged
merged 10 commits into from Feb 10, 2021

Conversation

nabokihms
Copy link
Member

@nabokihms nabokihms commented Dec 21, 2020

Overview

  • Add gomplate to the Docker image
  • Add entrypoint.sh script that renders the config file as a template

What this PR does / why we need it

Closes #1838

This PR solves a long time issue in Dex, name injecting secrets into the config file (especially on Kubernetes) without actually saving those secrets in less/non-secure storage layers. By using templating (and environment variables) we can create a config file runtime (when the container starts, in the entrypoint).

Obviously, the rendered config file is still saved to ephemeral storage, so it's not all the way secure, but anyone with access to the storage layer would have other means to get the secrets anyway.

A better long-term solution for secrets would be using environment variables directly and/or secret storage solutions (like Vault) or even KMS integration.

Special notes for your reviewer

Does this PR introduce a user-facing change?

Add [gomplate](https://github.com/hairyhenderson/gomplate) to the Dex docker image to provide config file templating features

Copy link
Member

@sagikazarmark sagikazarmark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like there is more we can do here:

  • I'd get rid of the entrypoint entirely
  • serve should be the default command IMHO
  • serve requires a config, so we need some sort of default

I'm not sure I'm a fan of reading config from stdin. I guess it's there so we don't write the resulting config to ephemeral storage, but it feels like a complication without benefits: anyone with access to the storage has already access to the container itself.

At least for now, I'd just write the configuration to /etc/dex/config.yaml.

WDYT?

@nabokihms
Copy link
Member Author

Everything sounds reasonable to me. The only thing that remains is implementation. I will work on it.

Dockerfile Outdated

CMD ["version"]
ENTRYPOINT ["dockerize", "-no-overwrite", "-template", "/etc/dex/config.tmpl:/etc/dex/config.yaml"]
CMD ["dex", "serve", "/etc/dex/config.yaml"]
Copy link

@heidemn heidemn Dec 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about moving "dex" to the end of ENTRYPOINT, to avoid a breaking change for current users of the Docker image?

ENTRYPOINT ["dockerize", "-no-overwrite", "-template", "/etc/dex/config.tmpl:/etc/dex/config.yaml", "dex"]
CMD ["serve", "/etc/dex/config.yaml"]

It may look less clean in the Dockerfile, but in my opinion it's better to avoid the breaking change.

If you still decide for the breaking change, at least it should be mentioned in the release notes ("Does this PR introduce a user-facing change?")

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable. Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I never like when an application is the entrypoint. It just ties the user's hands. Although it is a breaking change, but I don't think it'll affect most users. We could think of some sort of deprecation for this change to warn users in advance, but I'm not sure how effective it would be.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hardly believe that adding a deprecation warning will help. Mentioning such a change in the RM should be enough. However, for me, it looks better to leave dex at the entry point just because changing behavior is not required by this PR.

@heidemn
Copy link

heidemn commented Dec 31, 2020

Once my PR #1902 is merged, most Dockerize users will probably want to set DEX_EXPAND_ENV = false, to avoid another unexpected level of env expansion.

passwordConnector: {{ .Env.DEX_OAUTH2_PASSWORD_CONNECTOR }}
{{- end }}

enablePasswordDB: {{ default .Env.DEX_ENABLE_PASSWORD_DB "true" }}
Copy link

@heidemn heidemn Jan 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: What is the best way to pass an env variable that may contain YAML special characters like '"?
Is there a better solution than manually escaping single quotes?
bindPW: '{{ replace .Env.DEX_LDAP_BINDPW "'" "''" }}'

Since Dockerize uses text/template, I guess it's not aware of YAML syntax.

Of course the env variables could by convention already contain pre-escaped strings, but that would be rather strange.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I think it should be raised in the dockerize project. Helm has a quote filter that does exactly that.

Also, I see open issues in the project asking to add the sprig template library.

Copy link
Member

@sagikazarmark sagikazarmark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've looked into dockerize a bit more and I'm not sure it's gonna be good for us. The author doesn't answer to issues/PRs. I pinged him, let's if we get an answer.

Dockerfile Outdated
# Install dockerize to provide the way of config parametrization
ENV DOCKERIZE_VERSION v0.6.1
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
&& tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

amd64 is going to be a problem form arm builds. And sadly it looks like arm builds are not available yet: jwilder/dockerize#154

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The kind of a problem we can't solve on our own. Looks like we need to search for a better solution.

Copy link

@heidemn heidemn Jan 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The templating code of Dockerize is only 200 lines, since it's basically Go's text/template with some helper functions added.
On first sight, the only other feature from Dockerize that could be helpful for Dex is waiting for other dependencies (-wait , -timeout & co). And that can usually be solved with a crash loop.

Would it be an option to glue together ourselves Go templating with helpers from a well-maintained library like https://github.com/Masterminds/sprig in Dex?
Could work like this for the user:
$ dex serve config.yaml
$ dex serve --template config.tmpl

Sprig already includes env and default functions, similar to Dockerize.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, if you want to use dockerize, I recommend using its fork https://github.com/powerman/dockerize
This fork was created by an active contributor who was not satisfied with Jwilder's project management, communication, and so on.
Since then, a lot of improvements were done in Powerman's fork, incl. arm builds, for example.
The original dockerize seems to be an abandoned project.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm familiar with that fork, but I'm not sure I'm quite happy with the democratized maintenance model to implements:

Everyone who has contributed to the project may become a collaborator - just ask for it in PR comments after your PR has being merged.

Also, we really don't need all that functionality, so I'm happy with a simple templating solution. My only concern with gotemplate is its size.

@nabokihms
Copy link
Member Author

@sagikazarmark, I replaced dockerize with gomplate in this PR. Some concerns, problems, tasks to do:

  • entrypoint is back because gomplate can't work as an entrypoint
  • TARGETVARIANT is empty for arm/v6 and arm/v7 during the build
  • gomplate binary size is 36.7M
  • config template is located in /etc/dex, and directory is shared for nobody user
  • need to change description an title of the PR

Please take a look if you have time 🙏

@nabokihms nabokihms force-pushed the add-dockerize branch 2 times, most recently from 1cb0da1 to 8afe5f0 Compare January 28, 2021 13:46
@sagikazarmark sagikazarmark changed the title feat: Add dockerize to the Dex docker image feat: Add gotemplate to the docker image Jan 28, 2021
Copy link
Member

@sagikazarmark sagikazarmark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @nabokihms !

This looks like a good approach.

I had a few comments, can you please take a look at them?

Dockerfile Outdated Show resolved Hide resolved
entrypoint.sh Outdated Show resolved Hide resolved
examples/config-example.tmpl Outdated Show resolved Hide resolved
examples/config-example.tmpl Outdated Show resolved Hide resolved
examples/config-example.tmpl Outdated Show resolved Hide resolved
examples/config-example.tmpl Outdated Show resolved Hide resolved
examples/config-example.tmpl Outdated Show resolved Hide resolved
entrypoint.sh Outdated Show resolved Hide resolved
entrypoint.sh Outdated Show resolved Hide resolved
@nabokihms nabokihms force-pushed the add-dockerize branch 2 times, most recently from e62e270 to 394d7e5 Compare January 28, 2021 23:24
@nabokihms nabokihms force-pushed the add-dockerize branch 4 times, most recently from 46cc8d5 to 0c1feba Compare January 29, 2021 04:50
Dockerfile Outdated Show resolved Hide resolved
docker-entrypoint.sh Outdated Show resolved Hide resolved
nabokihms and others added 6 commits January 29, 2021 13:48
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
Co-authored-by: Márk Sági-Kazár <sagikazarmark@users.noreply.github.com>
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
docker-entrypoint.sh Outdated Show resolved Hide resolved
exec dex $@
;;
*)
exec $@
Copy link

@heidemn heidemn Jan 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this option, allowing it to bypass the templating by adding dex in front of the arguments. 👍
Maybe mention it in the "Usage" comment, so it's more obvious.

Copy link

@heidemn heidemn Jan 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should also adapt the section "Does this PR introduce a user-facing change?":

  • By default, Gomplate is now applied on the config file for docker run quay.io/dexidp/dex serve ....
  • To opt out, one can either adapt the command: docker run quay.io/dexidp/dex dex serve ...
    or change the entrypoint: docker run --entrypoint dex quay.io/dexidp/dex serve ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right! Whole description has to be rewritten.

Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
@@ -0,0 +1,46 @@
issuer: {{ getenv "DEX_ISSUER" "http://127.0.0.1:5556/dex" }}

Copy link

@heidemn heidemn Jan 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment that this config file is only an example / for development purposes?

And maybe mention in another comment that for escaping "unfriendly" input like passwords, this function could be used for escaping, to get valid YAML? https://docs.gomplate.ca/functions/strings/#strings-squote
(Sorry haven't tested it yet, but I'm assuming that such escaping is not done automatically by Gomplate)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense. Let's add a comment

Dockerfile Outdated Show resolved Hide resolved
Dockerfile Outdated Show resolved Hide resolved
Dockerfile Outdated Show resolved Hide resolved
Dockerfile Outdated Show resolved Hide resolved
Dockerfile Outdated Show resolved Hide resolved
Co-authored-by: Márk Sági-Kazár <sagikazarmark@users.noreply.github.com>
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
@sagikazarmark sagikazarmark changed the title feat: Add gotemplate to the docker image feat: Add gomplate to the docker image Feb 8, 2021
@sagikazarmark sagikazarmark added this to the v2.28.0 milestone Feb 10, 2021
Copy link
Member

@sagikazarmark sagikazarmark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good overall, thanks for working on this @nabokihms

There are two comments left, can you please take a look at those? Thanks!


ENV GOMPLATE_VERSION=v3.9.0

RUN wget -O /usr/local/bin/gomplate \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use the slim version instead for a smaller binary: https://github.com/hairyhenderson/gomplate/releases

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, does this work with every arm version? arm64, armv7? (The first one is GOARCH, the latter is variant AFAIK)

Copy link
Member Author

@nabokihms nabokihms Feb 10, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it does! I have tested with linux/arm/v7 and linux/arm64.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thanks!

@@ -0,0 +1,46 @@
issuer: {{ getenv "DEX_ISSUER" "http://127.0.0.1:5556/dex" }}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that makes sense. Let's add a comment

Co-authored-by: Márk Sági-Kazár <sagikazarmark@users.noreply.github.com>
Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
Copy link
Member

@sagikazarmark sagikazarmark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I think this is a great improvement!

@nabokihms
Copy link
Member Author

I have no time to change the description yet. Hope that I will be able to do it tonight.

@sagikazarmark
Copy link
Member

No worries, I've updated the PR description.

@sagikazarmark sagikazarmark merged commit 10597cf into dexidp:master Feb 10, 2021
xtremerui pushed a commit to concourse/dex that referenced this pull request Mar 16, 2021
The official docker release for this release can be pulled from

```
ghcr.io/dexidp/dex:v2.28.0
```

**Features:**

- Add c_hash to id_token, issued on /auth endpoint, when in hybrid flow (dexidp#1773, @HEllRZA)
- Allow configuration of returned auth proxy header (dexidp#1839, @seuf)
- Allow to disable os.ExpandEnv for storage + connector configs by env variable DEX_EXPAND_ENV = false (dexidp#1902, @heidemn-faro)
- Added the possibility to activate lowercase for UPN-Strings (dexidp#1888, @VF-mbrauer)
- Add "Cache-control: no-store" and "Pragma: no-cache" headers to token responses (dexidp#1948, @nabokihms)
- Add gomplate to the docker image (dexidp#1893, @nabokihms)
- Graceful shutdown (dexidp#1963, @nabokihms)
- Allow public clients created with API to have no client_secret (dexidp#1871, @spohner)

**Bugfixes:**

- Fix the etcd PKCE AuthCode deserialization (dexidp#1908, @bnu0)
- Fix garbage collection logging of device codes and device request (dexidp#1918, @nabokihms)
- Discovery endpoint contains updated claims and auth methods (dexidp#1951, @nabokihms)
- Return invalid_grant error if auth code is invalid or expired (dexidp#1952, @nabokihms)
- Return an error to auth requests with the "request" parameter (dexidp#1956, @nabokihms)

**Minor changes:**

- Change default themes to light/dark (dexidp#1858, @nabokihms)
- Various developer experience improvements
- Dependency upgrades
- Tons of small fixes and changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add dockerize to the docker image
4 participants