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

Allow environment variables substitition in values.yaml #10026

Open
drtobbyas opened this issue Aug 14, 2021 · 35 comments
Open

Allow environment variables substitition in values.yaml #10026

drtobbyas opened this issue Aug 14, 2021 · 35 comments
Labels

Comments

@drtobbyas
Copy link

Hi, I would like to propose allowing environment variable substitution in values.yaml file. Something like

// values.yaml

namespace: ${NAMESPACE}

replicaCount: ${REPLICA_COUNT}

port: ${PORT}

image:
  repository: ${IMAGE}
  pullPolicy: IfNotPresent
  tag: ${TAG}

imagePullSecrets:
  - name: regcred

fullnameOverride: ${APP_NAME}

This would be much similar to what is achievable with docker-compose.yml

// docker-compose.yml

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: base
    image: ${IMAGE}:${TAG}
    container_name: ${APP_NAME}
    ports:
      - '8080:8080'
    environment:
      PORT: ${PORT}
      NODE_ENV: ${NODE_ENV}
    restart: always

This is especially useful in CI/CD environments as values can be exported as environment variables and the value.yaml file is aware of such values and adequately substituted like in docker-compose.

Running Helm in a CI/CD usually involves constructing a separate values.yaml which will be passed as an argument to 'helm upgrade' command or directly setting each and every value in the command line as arguments

it is somehow daunting keeping multiple values.yaml file for different environments, and deployment targets and having to update each one for every change to a value.yaml

With this feature implemented, only one values.yaml may be maintained for all environments and deployment targets. The respective values are substituted as needed in the values.yaml (since in most cases, most of the values are already exposed and available as CI variable or environment variable in the CI environment). This will alleviate the pain of replicating/constructing/maintaining multiple values.yaml.

I'd be open to contributing a PR to this

@drtobbyas drtobbyas changed the title Allow environment variables substitition values.yaml Allow environment variables substitition in values.yaml Aug 15, 2021
@mattfarina
Copy link
Collaborator

Supporting environment variables has been discussed at length and there have usually been issues in how we would do it. A proposal to add them would need a Helm Improvement Proposal.

I'll give you an example of an issue. A common case is for one person or organization to create a chart while someone else consumes it. Helm is a package manager like apt, zypper, yum, etc. It's common for someone to create a chart (package) like the PostgreSQL chart by Bitnami and for many others to install it. Those many other may not know how to install or operate PostgreSQL but they can easily use it.

Many people also store sensitive information in environment variables. Sometimes it's a key, like a GitHub token, or something else sensitive. How does the security model work to help shield the Helm user (chart consumer) from a malicious chart author who wants to exfiltrate sensitive information? Note, these types of situations do come up in our regular security audits.

@drtobbyas
Copy link
Author

I believe the implementation should consist of replacing only environment variable names that match the placeholder names. The placeholder should have a special format like suggested above easily distinguishable and different from normal .yaml keys/values. Also to cater for the security of chart consumers, this feature could be made optional (disabled by default and can be enabled by educated users who knows what could go wrong). Chart authors can also be mandated and (code enforced/lint to ensure) all environment variable placeholders are clearly documented and visible to chart consumers.

@mattfarina
Copy link
Collaborator

Also to cater for the security of chart consumers, this feature could be made optional (disabled by default and can be enabled by educated users who knows what could go wrong).

Consider, for a moment, those who use apt to install a package on a Debian installation. How many of those who do that are really educated on what's happening on their system and being done by the package? A mass majority are doing things based on a trust model. Usually without verifying. They are not highly educated users on the topics at hand.

This is one of the powerful things about package managers. They enable someone with expert knowledge to package up that knowledge so others can consume it with little to no knowledge on their part.

Problems can arise when package authors start to assume that end users know nearly as much as they do. Package authors have a very different level of knowledge from package consumers. Yet, do many package authors realize that? We want to enable some advanced features but we want to do it in a way that chart authors don't make the experience more complex or less secure for more chart consumers.

This is why I suggest a Helm Improvement Proposal (HIP). It would be a way to look at the varying angles, consider the roles involved, look at the security, and propose something to work with all of that.

Chart authors can also be mandated and (code enforced/lint to ensure) all environment variable placeholders are clearly documented and visible to chart consumers.

This assumes that chart consumers read the docs. Do people read the docs before the reach a bump in the road? I'm not sure they do. Security by expecting people to read the docs may be a bad assumption.

@git001
Copy link

git001 commented Oct 13, 2021

As I have not found any easy way to use environment variables in the values.yaml have I used this line to full fill the requirements.

CI_ENVIRONMENT_SLUG=lala envsubst < charts/values.yaml| helm \
  --kubeconfig ../kubeconf-dev \
  -n mynamespace install --create-namespace -f - --dry-run myapp ./mycharts

The main point is -f -

@github-actions
Copy link

This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.

@github-actions github-actions bot added the Stale label Jan 12, 2022
@Noksa
Copy link

Noksa commented Jan 20, 2022

Any updates?

@github-actions github-actions bot removed the Stale label Jan 21, 2022
@jslay88
Copy link

jslay88 commented Jan 21, 2022

We already have chart provenance for those that are wanting to enforce security, and the charts are readable by anyone. I think the security issue is a bit moot in my opinion, not that security is a moot issue, just out of scope for a package manager. No package manager I know of, goes beyond provenance to ensure a collected and installed package is not reading environment variables and sending them off, nor do you have the same level of visibility into said installed packages from something like apt as you do with Helm. You could even go yet another step further and version lock and sha256sum a chart outside of Helm after its grabbed too, as most people that are at this level of concern would probably already do.

Bash/Shell already have a way to handle defaults for an envvar when not defined, for which that syntax standard could also be followed. You could also take a system that was running an application with settings define via envvar, deploy using helm from that system, and it would essentially be able to then mimic that systems config when deploying the chart to the cluster, say during a migration to k8s. Using postgres as an example, going from a docker-compose system setup where you would define POSTGRES_USER and POSTGRES_PASSWORD when deploying the instance, that would be able to easily transplant into a Secret template via default value in Bitnami's Postgres chart values.yaml being postgresqlUsername: ${POSTGRES_USER:-postgres} and postgresqlPassword: ${POSTGRES_PASSWORD} when deploying with Helm, with no additional mapping from the user. Not to mention, this could dramatically increase flexibility with support of .env files.

Having been deploying things via chart for a while now, its getting a bit old having to --set everything when wanting to bring something in from an environment variable as a value override, especially when you are forced to bring it in via envvar.

@matti
Copy link

matti commented Jan 23, 2022

I'm just the same thing what @git001 is doing in #10026 (comment) and bypassing all security blah blah to get stuff done.

so just make a decision to:
a) support this as is with some --yes-I-know-what-I-am-doing
b) not support this "because of unix philosophy and use envsubst etc to roll your own substitution"

both outcomes are fine.

@matti
Copy link

matti commented Jan 31, 2022

workaround: multiple value files substituted and merged together:

    values=${@:1}

    opts=""
    tmpfiles=""
    for value in $values; do
      tmpfile=$(mktemp)
      tmpfiles="${tmpfiles} ${tmpfile}"

      envsubst < "${value}" > $tmpfile
      opts="${opts} -f ${tmpfile}"
    done

    for tmpfile in $tmpfiles; do
      cat $tmpfile
    done

    helm upgrade --install \
      "${name}" "${name}/${chart}" \
      --create-namespace --namespace "${name}" \
      --version "${version}" \
      $opts

@jslay88
Copy link

jslay88 commented Feb 9, 2022

I'm just the same thing what @git001 is doing in #10026 (comment) and bypassing all security blah blah to get stuff done.

so just make a decision to: a) support this as is with some --yes-I-know-what-I-am-doing b) not support this "because of unix philosophy and use envsubst etc to roll your own substitution"

both outcomes are fine.

While envsubst works in some cases, it does not follow the bash/sh syntax when defining a default value, which I think is critical if you were to add support for this in Helm. It also is not a thing on Windows.

Ergo, there is no support within the values.yaml for something like ${MY_VAR:-test} with envsubst, which would be critical to a public chart (say, bitnami postgresql).

@git001
Copy link

git001 commented Feb 9, 2022

I fully agree to the previous comments. helm should have the option to use environment variables maybe with a flag --I_really_know_what_I_m_doing

@timsamart
Copy link

To ensure integration in our DevOps Processes this improvement is essential!

@HyungJune
Copy link

This feature might be useful when we use ArgoCD.
I didn't find out the helm way to solve the problem changing an image tag automatically in a value file when our application is builded. To solve this problem, I implemented a simple golang program which helps those changes (read a value file, get a tag as an input, and change the image tag value in the value file). It can make CI/CD pipeline but, not suitable.
I would say that getting environment variables as a form of .tpl or other way and using them on templates are essential when we construct CI/CD pipeline as a declarative form.

@joelezellLP
Copy link

+1 on this improvement.

@niiku
Copy link

niiku commented Jul 22, 2022

This feature might be useful when we use ArgoCD. I didn't find out the helm way to solve the problem changing an image tag automatically in a value file when our application is builded. To solve this problem, I implemented a simple golang program which helps those changes (read a value file, get a tag as an input, and change the image tag value in the value file). It can make CI/CD pipeline but, not suitable. I would say that getting environment variables as a form of .tpl or other way and using them on templates are essential when we construct CI/CD pipeline as a declarative form.

@HyungJune Maybe have a look at https://baloise.github.io/gitopscli/

@developerrajtomar
Copy link

developerrajtomar commented Sep 8, 2022

Guys, kindly let me know if there is any workaround for this proposal. Even, I am in the situation where I need to substitute USERNAME and PASSWORD to configure SASL authentication mechanism for kafka-connect helm chart. Both USERNAME and password will be the part of key-vault secret which the SASL_JAAS_CONF is part of env at the end the value will look like below:

env:
- name: CONNECT_SASL_JAAS_CONFIG
   value: org.apache.kafka.common.security.scram.ScramLoginModule required username="${USERNAME}" password="${PASSWORD}";

Currently the value is getting passed as is to the env variable and I am unable to replace its actual content in the helm way.

Any help will be appreciable.

@jslay88
Copy link

jslay88 commented Sep 8, 2022

@matti
Copy link

matti commented Sep 8, 2022

yes, envsubst or sed

@bery
Copy link

bery commented Sep 19, 2022

I have created a simple helm plugin which imports environment variables and passes them to helm as set values

https://github.com/bery/helm-set

export HELM_VAR_replicaCount=3
helm set upgrade --install --dry-run=false xxx ealenn/echo-server

Result

helm upgrade upgrade --install --dry-run=false xxx ealenn/echo-server --set replicaCount=3

@NicolasTobias
Copy link

We were facing the same problem, the missing possibility to add variables to values.

@github-actions
Copy link

This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.

@github-actions github-actions bot added the Stale label Feb 16, 2023
@vicenteherrera
Copy link

vicenteherrera commented Feb 17, 2023

This should be possible with vals in combination with the envsubst backend. The reference in a values file would look very nice:

mysqlPassword: ref+envsubst://$MYSQL_PASSWORD

But the way to get helm to use vals is so convoluted, that other examples already provided for using envsubsts command or sed directly seems more elegant:

helm template mysql-1.3.2.tgz --set mysqlPassword='ref+envsubst://$MYSQL_PASSWORD' | vals ksdecode -o yaml -f - | tee manifests.yaml
cat manifests.yaml | ~/p/values/bin/vals eval -f - | tee all.yaml
kubectl apply -f all.yaml

There is a plugin that should make it easier to incorporate:
https://github.com/jkroepke/helm-secrets

I haven't used it because I'm trying to solve this on helmfile, which should work out-of-the-box with vals, but it isn't doing so for me with environment variables... but I leave those links in case they are useful to somebody using directly helm.

@github-actions github-actions bot removed the Stale label Feb 18, 2023
@OnyinyeAladiume22
Copy link

Nothing yet then?

@jeremybusk
Copy link

jeremybusk commented May 28, 2023

This should be allowed. It's silly it isn't already unless there is a good reason not to. Often, more complex deploys have config variables in values.yaml that may need to have dynamic or sensitive information in them and while you can use envtpl (if no existing {{}} in values.yaml) or envsubst but it is a pain to do so and would prefer this option is built into helm cli. I would think it would take a limited coding effort to add this in and if you ask around it would save a lot time then individual users editing template files for their own custom charts.

@netikras
Copy link

netikras commented Jun 7, 2023

Supporting environment variables has been discussed at length and there have usually been issues in how we would do it. A proposal to add them would need a Helm Improvement Proposal.

I'll give you an example of an issue. A common case is for one person or organization to create a chart while someone else consumes it. Helm is a package manager like apt, zypper, yum, etc. It's common for someone to create a chart (package) like the PostgreSQL chart by Bitnami and for many others to install it. Those many other may not know how to install or operate PostgreSQL but they can easily use it.

Many people also store sensitive information in environment variables. Sometimes it's a key, like a GitHub token, or something else sensitive. How does the security model work to help shield the Helm user (chart consumer) from a malicious chart author who wants to exfiltrate sensitive information? Note, these types of situations do come up in our regular security audits.

I'd argue the legitimacy of this attack vector. The simple answer is: it doesn't. It's not entirely Helm's business to make sure users don't use it with malicious charts. Same as Maven [and its plugins], Gradle [and its plugins], kubectl apply, etc. It is up to the user to ensure he knows what he's doing and that the repository/chart he's using can be trusted.

The only really valid problem I can think of is scoping: all the charts are run in the same environment and multiple charts can be referring to the same env variable for different purposes. In this case, even a defaulting mechanism (like shell's ${VAR:-default_value}) will be helpless.

@vicenteherrera
Copy link

Supporting environment variables has been discussed at length and there have usually been issues in how we would do it. A proposal to add them would need a Helm Improvement Proposal.
I'll give you an example of an issue. A common case is for one person or organization to create a chart while someone else consumes it. Helm is a package manager like apt, zypper, yum, etc. It's common for someone to create a chart (package) like the PostgreSQL chart by Bitnami and for many others to install it. Those many other may not know how to install or operate PostgreSQL but they can easily use it.
Many people also store sensitive information in environment variables. Sometimes it's a key, like a GitHub token, or something else sensitive. How does the security model work to help shield the Helm user (chart consumer) from a malicious chart author who wants to exfiltrate sensitive information? Note, these types of situations do come up in our regular security audits.

I'd argue the legitimacy of this attack vector. The simple answer is: it doesn't. It's not entirely Helm's business to make sure users don't use it with malicious charts. Same as Maven [and its plugins], Gradle [and its plugins], kubectl apply, etc. It is up to the user to ensure he knows what he's doing and that the repository/chart he's using can be trusted.

The only really valid problem I can think of is scoping: all the charts are run in the same environment and multiple charts can be referring to the same env variable for different purposes. In this case, even a defaulting mechanism (like shell's ${VAR:-default_value}) will be helpless.

The way I use env variable in these situations is that I define them just for the execution I'm doing. So if I want to define a port with an env variable, I would do:
PORT_PROXY=8080 helm install my-chart chart-source
That way the variable is not even defined in the machine, and I can redefine it again for a different chart installation.
It would be more problematic for helmfiles, but that is not for this thread.

@rbi
Copy link

rbi commented Jul 9, 2023

I just stumbled across this issue when seeing some custom sed substitution magic in our CI/CD setup manipulating values.yml files. I thought that can't be necessary as helm itself is already a kind of substitution technology but it turns out that is and this is one of the suggested workarounds for the missing environment variable substitution in Helm.

So here are my 2 cents on this topic. It could be done similarly to what Spring Boot does. Spring boot allows to set any configuration variable via environment variables. You just have to have to stick to some naming conventions for the environment variables. This way helm chart authors do not need to guess what users may want to override via environment variables and what not. They do not need to know about that feature at all.

To address the already mentioned security concerns this feature could be off by default and you could activate it with the already mentioned --i-know-what-i'm-doing command line switch (maybe --enable-values-from-env).

An example on how this would work. Given the following values.yml.

some-top-level:
  child1: "some default"

You could override this e.g. when doing helm upgrade --enable-values-from-env with an environment variable.

SOMETOPLEVEL_CHILD1="overridden value"

without the need to explicitly state in the values.yml that this config was intended to be overridden by an environment variable. This is consistent with the --set mechanism where you can override arbitrary configs as well.

@fredleb
Copy link

fredleb commented Aug 6, 2023

Same idea as envsubst, but slightly more powerful: https://jinja.palletsprojects.com/

We've used that at work with success. Hope that helps !

Copy link

github-actions bot commented Nov 5, 2023

This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.

@github-actions github-actions bot added the Stale label Nov 5, 2023
@dkmiller
Copy link

dkmiller commented Nov 6, 2023

This feature would be seriously helpful.

@github-actions github-actions bot removed the Stale label Nov 7, 2023
@hexiaofeng
Copy link

This is an alternative solution that supports default values。 https://github.com/a8m/envsubst

@git001
Copy link

git001 commented Nov 13, 2023

@hexiaofeng

This is an alternative solution that supports default values。 https://github.com/a8m/envsubst

Yep and is a suggested solution in #10026 (comment) 😀

Copy link

This issue has been marked as stale because it has been open for 90 days with no activity. This thread will be automatically closed in 30 days if no further activity occurs.

@github-actions github-actions bot added the Stale label Feb 12, 2024
@rbi
Copy link

rbi commented Feb 12, 2024

Still an issue, please unstale.

@github-actions github-actions bot removed the Stale label Feb 13, 2024
@interone-ms
Copy link

@hexiaofeng

This is an alternative solution that supports default values。 https://github.com/a8m/envsubst

Yep and is a suggested solution in #10026 (comment) 😀

it's not a perfect solution though as it breaks down with stuff that needs quoting because it has special meaning in YAML, multiline and whatnot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests