Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upSupport for environment variable substitution in configuration file #2357
Comments
This comment has been minimized.
This comment has been minimized.
|
We've previously discussed several times and decided against. For simplicity we keep to one way to configure a given thing, otherwise we'd end up with 4-5 ways. |
brian-brazil
closed this
Jan 21, 2017
This comment has been minimized.
This comment has been minimized.
alexellis
commented
Sep 17, 2017
|
This could be a particularly powerful way to configure Prometheus in a cluster without the burdensome task of a separate config file for every configuration you can ever deploy. |
brian-brazil
added
the
wont-fix
label
Sep 17, 2017
This comment has been minimized.
This comment has been minimized.
nutchalum
commented
Oct 5, 2017
|
It's a nice to have. |
This comment has been minimized.
This comment has been minimized.
Nick-Triller
commented
Nov 15, 2017
•
|
Environment variable substitution would allow to keep sensitive data like passwords used for remote read/write out of the config file, too. InfluxData recently mentioned environment variable substitution in config files would be a useful feature in their eyes. |
This comment has been minimized.
This comment has been minimized.
ababushkin
commented
Dec 14, 2017
|
I don't think it would cause usability issues guys, its pretty common to use environment variable substitution in config files like these. Any chance to revise that decision? Here are some benefits:
Am I missing something here? |
This comment has been minimized.
This comment has been minimized.
boeboe
commented
Dec 24, 2017
•
|
Any update on this? Related to #2664 Eventually we just ended up having separate configuration files per cluster, which was annoying since it was an exception among other services deployed within our clusters. PS: another option is to provide small wrapper script doing this cluster specific substitions (sed -i prometheus.yml like) before actually starting prometheus. You will need a proper signal handling mechanism like dump-init however (https://github.com/Yelp/dumb-init), since you're prometheus will not be running as PID 1 anymore in this case.
... and within your entrypoint script:
The disadvantage of this approach is you're introducing an external component dumb-init, breaking single process per container best practices, which some might not be willing to do. |
This comment has been minimized.
This comment has been minimized.
|
We have similar issues when we run Prometheus in 2-replica statefulset which reuses single configmap. To support HA we have
This is not fun and this solution screams for better approach. But I feel like this might be rather Kubernetes issue not enabling that, not necessarily Prometheus one. |
This comment has been minimized.
This comment has been minimized.
|
Maybe moving |
This comment has been minimized.
This comment has been minimized.
A small tip: When you are using the shell like this where application is the last thing you are running do I'm unsure of the wisdom of using a hostname as an external label, that's going to make any remote storage endpoint have labels vary as Prometheus moves around over time. Two separate statefulsets with different label values like mydc1 and mydc2 might be better. |
This comment has been minimized.
This comment has been minimized.
|
Cool, thanks for the advice! Our host name is actually pod name so I think this is fine (: Won't change easily. |
This comment has been minimized.
This comment has been minimized.
|
Yea, the name for stateful sets is deterministic in contrast to deployments, where pods get a random suffix. So it will always be |
This comment has been minimized.
This comment has been minimized.
liyaka
commented
Feb 27, 2018
|
I need to configure azure_sd_configs with sensitive info like client_secret and etc. |
This comment has been minimized.
This comment has been minimized.
Environment variables are a bad idea for secrets. Ansible has its own secret and templating support, which is the standard way to approach this. |
This comment has been minimized.
This comment has been minimized.
abh
commented
Apr 13, 2018
|
FWIW, the prometheus-config-reloader for prometheus-operator looks to have implemented a solution for this for the statefulset use case recently: coreos/prometheus-operator#1132 coreos/prometheus-operator@608e714#diff-a2dba0afa9edde401541fc9054415bba |
This comment has been minimized.
This comment has been minimized.
|
If you use Thanos you have that out-of-the-box as well: https://github.com/improbable-eng/thanos/blob/master/cmd/thanos/sidecar.go#L73 |
This comment has been minimized.
This comment has been minimized.
orubel
commented
Apr 24, 2018
|
One reason to have this is so that you can have better devops for SWARMS If you are doing lots of builds, you want to be able to template your SWARMS and this does NOT make that possible. I build 4-50 node swarms constantly based on customer demands and being able to dynamically configure them would be IDEAL and save me hours. |
This comment has been minimized.
This comment has been minimized.
dbendelman
commented
May 6, 2018
|
B"H We solved this by creating an entrypoint script that preprocesses environment variables before calling the binary. Example showing how to set
Here are the Prometheus and Alertmanager images, with sources linked there. Multiple tags are available depending on the version you need. These are super bare-bones wrappers around the official images, simply working around this particular issue and then getting out of the way. The Prometheus authors made a great product and are making sound arguments for not including this functionality natively. The above images, however, might help people whose infrastructures or policies allow for taking a more relaxed approach. |
dbendelman
referenced this issue
May 6, 2018
Closed
Add Dockerfile environment variables to control CMD arguments #3385
This comment has been minimized.
This comment has been minimized.
djbingham
commented
May 14, 2018
What about using Docker secrets? My understanding is the expected way of controlling secret values in containers is to add a Docker secret, which generates a file inside your container, then within the container read that file into environment variables at runtime. |
This comment has been minimized.
This comment has been minimized.
|
@djbingham That is still putting secrets in environment variables. |
This comment has been minimized.
This comment has been minimized.
djbingham
commented
May 14, 2018
|
@brian-brazil Yes it is, but I'm led to believe (from the official documentation for Docker) that this is the expected way to handle such things. If that is actually a bad idea, please could you elaborate on why? |
This comment has been minimized.
This comment has been minimized.
|
See http://movingfast.io/articles/environment-variables-considered-harmful/ and https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/ for the reasoning. Environment variables were never designed with secrets in mind, nor are they traditionally a place to put secrets. |
This comment has been minimized.
This comment has been minimized.
djbingham
commented
May 14, 2018
|
Good explanations, thanks. |
alexellis
referenced this issue
May 14, 2018
Closed
Secrets with similar keys cause deploy failure #193
This comment has been minimized.
This comment has been minimized.
dbsanfte
commented
Jun 18, 2018
•
|
Secrets are being used as an excuse to avoid adding some pretty basic and expected functionality, methinks. http://docs.grafana.org/installation/configuration/#using-environment-variables Justify what's wrong with that, as not just Grafana but NPM and others have the exact same regime of overrides. |
This comment has been minimized.
This comment has been minimized.
fljmayer
commented
Jul 13, 2018
|
So we have to put environment-specific proxy settings into a configuration file that can otherwise be kept environment-independent? That doesn't seem like good solution. |
This comment has been minimized.
This comment has been minimized.
sgeisbacher
commented
Jul 28, 2018
•
@brian-brazil but storing them statically in config-files in your git-repo is better?
@brian-brazil but running "config-pre-render-scripts" to set imho sometimes you have no clue what you are talking about, sorry. |
This comment has been minimized.
This comment has been minimized.
Jake-Smullin
commented
Aug 30, 2018
|
Env variables make so much sense here... Can't check in my AWS creds for an ec2_sd scrape job, and mounting them in as secrets to ENV vars and then leaving in the scrape config $ACCESS_KEY for example would be perfect. |
This comment has been minimized.
This comment has been minimized.
speedooo
commented
Sep 13, 2018
•
|
Is it possible use the same way as file_sd_configs reading details fromm external file for external_labels?just read key-value pair |
This comment has been minimized.
This comment has been minimized.
mohr-michael-adam
commented
Sep 19, 2018
|
Is it safe to launch Prometheus (or AlertManager) then erase the config file after it is running? This way the sensitive data only exists on disk in plaintext for a brief moment. Not claiming this to be secure but it helps. |
This comment has been minimized.
This comment has been minimized.
logemann
commented
Nov 5, 2018
|
I think its obvious for several reasons to have that feature. For me, i want to have a more dynamic way of definiting ports of targets depending on the docker-compose.yml file. But i could think of thousands more. |
This comment has been minimized.
This comment has been minimized.
zakkg3
commented
Nov 13, 2018
•
|
This should be a must-have, not a nice to have. |
This comment has been minimized.
This comment has been minimized.
logemann
commented
Nov 13, 2018
|
@zakkg3 you wont get any positive feedback from the author regarding that. As you see in my closed reminder case. Sad but true. He dont mind that any other framework/product has such a mechanism. |
This comment has been minimized.
This comment has been minimized.
zakkg3
commented
Nov 14, 2018
|
I see @logemann I ve made a custom image with confd to workaround, feel free to fork: |
This comment has been minimized.
This comment has been minimized.
nmaupu
commented
Nov 21, 2018
•
|
I am also surprised not to be capable of doing that. I would rather prefer using http_proxy environment variable instead of having to put this in
would be much much better. By the way, alertmanager doesn't seem to use |
This comment has been minimized.
This comment has been minimized.
Qix-
commented
Jan 21, 2019
You're encouraging poor security practices by keeping credentials on the filesystem during e.g. Dockerfile-based builds. Not being able to configure secrets via environment variables is going to cause vulnerabilities in production systems. It's quite sad it's not available. |
This comment has been minimized.
This comment has been minimized.
|
See #2357 (comment) above, putting secrets in environment variables is not a good security practice. |
This comment has been minimized.
This comment has been minimized.
Qix-
commented
Jan 21, 2019
•
|
@brian-brazil You're basing that off one article that has a bunch of holes in it. You can easily see environment variables using procfs, sure. They are also inherited to child processes, sure. But this is assuming you're running untrusted code in production in the first place. Most people that know what they're doing, or have proper QA processes in place, are not doing this. Assuming a container has been compromised means that any form of secret storage is vulnerable. The only alternative is to somehow detect that the production application has consumed the credentials and to dispose of them - which means you have to trust the application to also dispose of them in memory. That's a tall order for most software today, and highly unrealistic in terms of threat modeling - to require that degree of secrets handling isn't necessary in what I'd consider the "common case" for most production cases. The threat model generally takes into account the method of secret handling. Storing credentials in a repository is a non-starter. That violates federal regulations under which we operate. I assume the same applies to many people. Storing credentials in k8s secrets doesn't work because we're stuck with volume mounts or environment variables, both of which you're staunchly against. As you've mentioned elsewhere, you are now expecting us to write glue code that initializes the configuration at runtime as an added step using a substitution method (e.g. templates) to pull in the secrets from volume mounts or environment variables anyway in order to build up prometheus configuration. That's insane. It isn't your job to dictate my system's threat model. It's my job. That's what I was hired to do. You have an army of users asking you for this feature. You're declining for a dogmatic reason that contradicts many of the points made against both your reasoning as well as against the articles you yourself linked to back up your viewpoint. Not having this feature is getting in the way of my work, and causing me more security overhead than not having it as I have to write configuration scripts which implies error surface area and liability. Plus, it's another piece of code I have to have audited. Please reconsider. Even if you put a warning label in big, red capital letters next to the documentation for environment configuration, whatever it takes. EDIT: some more points: But sometimes software dumps out its environment in times of debugging or failure.No it doesn't. I've yet to see a production-ready piece of software recklessly dump the entirety of its environment map to stdout/err/file/etc. when it dies. Not only is it needless, it doesn't do anything to help developers anyway. Rarely are problems in production related to the environment, especially with containers. But child processes can maliciously access the parent process's secrets if they're exposed via environment variables.This is assuming you're running software that runs child processes, and those child processes aren't also trusted. Compartmentalized security, credential auditing, rotation, codebase auditing, firewall rules - all of these things that should be happening will combat this. But writing to the filesystem prevents all of that for free.Again, this is only a net benefit if you are worried about the process somehow transmitting the credentials - which, in most cases, is not something you would worry about. Plus, if it's running in the container, you should be modeling the security as inherently compromised by the child process anyway - therefore, the assumption is that the child process can still read the filesystem just fine. But what about UNIX permissions?Sure, I guess. It's still a weak argument against proper security modeling, and only increases the chance for mis-configuration from within the container itself. There's still the problem of secrets storage and transportation into the container or machine itself, too. That's fixed by exactly none of this. Also, it's better if the application disposes of the credentials from memory too, which means you can unlink the credentials from the filesystem.Sounds great - except not even prometheus can realistically do this. It runs based on HTTP + REST, which means it has to keep any URIs or bearer tokens in memory, which also means that it can't feasibly dispose of them if it wants to make more than one read/write. |
This comment has been minimized.
This comment has been minimized.
nmaupu
commented
Jan 21, 2019
|
Using environment variables for configuration is not necessary to pass critical secrets to a container. My use case (using HTTP_PROXY env vars) is not really secret, it is pushed via a podpreset and it would be neat to be reused instead of repeating the code elsewhere ... |
This comment has been minimized.
This comment has been minimized.
alexellis
commented
Jan 21, 2019
•
|
On the OpenFaaS project we are also advising users not to store secrets in environmental variables, but to use secrets in files instead. I saw that the configuration for HTTP alert endpoints now supports reading credentials from a file at runtime. This would be ideal for other secrets too. |
This comment has been minimized.
This comment has been minimized.
Qix-
commented
Jan 21, 2019
•
Why? How is that any better? |
This comment has been minimized.
This comment has been minimized.
fvclaus
commented
Apr 3, 2019
•
|
Wow. This is pretty ignorant. I am running prometheus in a docker container. To force my environment variables in, I modified the entrypoint of the official image and run this script instead: #!/bin/ash
set -e
cp /etc/prometheus/prometheus-template.yml /etc/prometheus/prometheus.yml
env |
while IFS='=' read -r name value
do
# Convert to lowercase: FOO -> foo
name=$(echo $name | tr '[:upper:]' '[:lower:]')
# Replace sed seperator character / -> \/
value=$(echo $value | sed 's;/;\\/;g')
# Replace occurrences in file.
sed --in-place=.bak "s/((${name}))/${value}/g" /etc/prometheus/prometheus.yml
done
/bin/prometheus --config.file=/etc/prometheus/prometheus.yml \
--log.level=debug \
--web.console.libraries=/etc/prometheus/console_libraries \
--web.console.templates=/etc/prometheus/consoles |
This comment has been minimized.
This comment has been minimized.
dbsanfte
commented
Apr 16, 2019
|
Users are already routing around the brain damage of @brian-brazil. Very satisfying to watch. |
This comment has been minimized.
This comment has been minimized.
Qix-
commented
Apr 16, 2019
•
|
@alexellis Please respond. How does that help? I'm genuinely curious. |
This comment has been minimized.
This comment has been minimized.
abh
commented
Apr 17, 2019
It’s hard to be motivated to help when you start out like that.
Pay attention to the file paths, use a temporary file in /tmp if necessary. Remove the -i option from sed if you don’t need the backup file created (or again, use a different path). Those are basic file permission / shell scripting things, unrelated to Prometheus. |
This comment has been minimized.
This comment has been minimized.
Qix-
commented
Apr 17, 2019
|
/tmp is not magic. What benefits does it provide in this case? I don't see how a backup file makes any difference. Neither of those things have anything to do with file permissions. Please explain @abh. |
This comment has been minimized.
This comment has been minimized.
abh
commented
Apr 17, 2019
|
The message I replied to originally mentioned how the proposed shell script got various permission errors.
Having a “sidecar” to process configuration and reloads is a completely reasonable and easily implementable setup. The important part is for the primary software to have good facilities for managing configuration reloads, implementing every possible configuration source or templating doesn’t make any sense.
You want environment variables. I want consul. She wants a grpc api. He wants integration with an ansible system.
|
dopuskh3 commentedJan 21, 2017
•
edited
I think that would be a good idea to substitute environment variables in the configuration file.
That could be done really easily using os.ExpandEnv on configuration string when loading configuration string.
That would be much easier to substitute environment variables only on configuration values. go -ini provides a valueMapper but yaml.v2 doesn't have such mechanism.