Live data from Hacker News

Environment variables are a legacy mess: Let's dive deep into them

allvpv.org

81–90 of 194 posts

Re: Environment variables are a legacy mess: Let's dive deep into them

#81
post #3

Environment variables are often used to pass secrets around. But, despite its ubiquity, I believe that's a bad practice: - On Linux systems, any user process can inspect any other process of that same user for it's environment variables. We can argue about threat model but, especially for a developer's system, there are A LOT of processes running as the same user as the developer. - IMO, this has become an even more…

> Any good solutions for passing secrets around that don't involve environment variables or regular plain text files?

Honestly, my answer is still systemd-creds. It's easy to use and avoids the problem that plain environment variables have. It's a few years old by now, should be available on popular distros. Although credential support for user-level systemd services was added just a few weeks ago.

A TL;DR example of systemd-creds for anyone reading this:

    # Run the initial setup
    systemd-creds setup

    # This dir should have permissions set to 700 (rwx------).
    credstore_dir=/etc/credstore.encrypted
    # For user-level services:
    # credstore_dir="$HOME/.config/credstore.encrypted"
    
    # Set the secret.
    secret=$(systemd-ask-password -n)
    
    # Encrypt the secret.
    # For user-level services, add `--user --uid uidhere`.
    # A TPM2 chip is used for encryption by default if available.
    echo "$secret" | systemd-creds encrypt \
        --name mypw - "$credstore_dir/mypw.cred"
    chmod 600 "$credstore_dir/mypw.cred"
You can now configure your unit file, e.g.:

    [Service]
    LoadCredentialEncrypted=mypw:/etc/credstore.encrypted/mypw.cred
The process you start in the service will then be able to read the decrypted credential from the ephemeral file `$CREDENTIALS_DIR/mypw`. The environment variable is set automatically by systemd. You can also use the command `systemd-creds cat mypw` to get the value in a shell script.

At least systemd v250 is required for this. v258 for user-level service support.

Re: Environment variables are a legacy mess: Let's dive deep into them

#82
post #3

Environment variables are often used to pass secrets around. But, despite its ubiquity, I believe that's a bad practice: - On Linux systems, any user process can inspect any other process of that same user for it's environment variables. We can argue about threat model but, especially for a developer's system, there are A LOT of processes running as the same user as the developer. - IMO, this has become an even more…

You've described the classic Unix security model, with minor improvements. While decent for the time it is showing its age. Specifically the difficulty in adapting to cheap, ubiquitous computing which it wasn't designed for.

If you need to keep secrets from other processes—don't run them under the same user account. Or access them remotely, although that brings other tradeoffs and difficulties.

Re: Environment variables are a legacy mess: Let's dive deep into them

#83
post #18

We're almost rid of dotfiles in $HOME. Can we please also get rid of the abuse of environment variables for configuration? There is no reason your program needs to muck up the environment table of every process by defining MY_PROGRAM_API_KEY instead of taking a command line argument or reading a configuration file. It's not "secure" just because it's not on the command line. And it will mess up for users because it's…

This problem is also removed by just not exporting the variables. Also you can just pass an envp to execvE.

"MY_APP_SECRET_KEY=bla myapp" hardly accomplishes anything substantial over "myapp --secret-key=blah" It's just a less robust and less well-supported command-line interface. It's not supported by most gui launchers, PowerShell, nor many cron implementations, for example.

Re: Environment variables are a legacy mess: Let's dive deep into them

#84

Earlier quoted context omitted.

Because you can't run the container, even for development outside Kubernetes. Yes, you can mount Secrets as Volumes or Env Var in Kubernetes which is fine but I'm not talking about "How you get env var/secret" but "Methods of dealing with config."

This is where I like things like Tilt. If you're deploying to a k8s cluster, it's probably a good idea to do local dev in as close to a similar environment as possible. Bit more of an initial hurdle than "just run the docker image"; however.

I've look at Tilt and it's another abstraction for Kubernetes which rarely ends well at scale.

However, most of time, Devs don't need to develop on Kubernetes since it's just Container Runtime and Networking Layer they don't care about. They run container, they connect to HTTP endpoint to talk to other containers, they are happy. Details are left to us Ops people.

Re: Environment variables are a legacy mess: Let's dive deep into them

#85

Earlier quoted context omitted.

You still need to present that to Application. So Command Line leaks worse than Env Var. Config file, see original post for problems. Env Var, see blog for problems.

No I meant a property in the application config. For example mbsync/isync does this.

You have a config file, it needs to have secrets so likely you are going to run some templating system where you replace dbpassword: ${dbPassword} with password from some secret system. Hopefuly you understand possible issues with any templating system that could result in replacement failures.

String manipulating is one of those "This is easy" until it's not.

Re: Environment variables are a legacy mess: Let's dive deep into them

#86

Earlier quoted context omitted.

How is the kubernetes secret API lock in? Genuinely wondering - were you trying to use that deployment yaml for something other than a kubernetes deployment? For most applications, you should be mounting the secret on your application, then you can inject it as either an environment variable or a json file that your application reads in an environment agnostic way. Then, on the backend, you can configure etcd to use…

Because you can't run the container, even for development outside Kubernetes. Yes, you can mount Secrets as Volumes or Env Var in Kubernetes which is fine but I'm not talking about "How you get env var/secret" but "Methods of dealing with config."

Yes you can? The container should be completely agnostic to the fact that it's running in kubernetes. You can do config the same way. Configmaps are mounted as regular files and environment variables. The application doesn't care if the configmap came from the cluster resource or a file your created on your dev machine with dev credentials. You can mount local files into the container yourself. It's docker run -v "source:destination" I think.

Re: Environment variables are a legacy mess: Let's dive deep into them

#87
post #11
post #3

Environment variables are often used to pass secrets around. But, despite its ubiquity, I believe that's a bad practice: - On Linux systems, any user process can inspect any other process of that same user for it's environment variables. We can argue about threat model but, especially for a developer's system, there are A LOT of processes running as the same user as the developer. - IMO, this has become an even more…

Any good cross-platform and easy ways to share secrets without using environment variables?

SOPS can be part of the solution. It takes care of encrypting and decrypting config files.

https://github.com/getsops/sops

Re: Environment variables are a legacy mess: Let's dive deep into them

#88

I get anxiety whenever I need to set an environment var on Linux. There are (somewhat distro-specific) ways that work properly, but the usual procedures you find online stops working once you reboot (or close the terminal I think?). They should add a simple env var GUI like Windows has that just works , and isn't terminal-specific. Windows has the annoyance of needing to restart the the terminal (or open a new one) f…

https://xkcd.com/927/ - Standards

Situation: There are 14 competing ways to set environment variables on Linux

We should create a universal way that just works and isn't terminal specific to set environment variables!

Situation: There are 15 competing ways to set environment variables on Linux

Re: Environment variables are a legacy mess: Let's dive deep into them

#89
post #30

Earlier quoted context omitted.

Since at least 2012, environment variables have been at least as secure as ordinary memory: commit b409e578d9a4ec95913e06d8fea2a33f1754ea69 Author: Cong Wang Date: Thu May 31 16:26:17 2012 -0700 proc: clean up /proc/ /environ handling You can't read another process's environment unless you can ptrace-read the process, and if you can ptrace-read the process you know all its secrets anyway. cmdline is a different story…

Just to clarify, that means that by default every process of the same user can access the variables. But it doesn't really matter because by default every process of the same user can read any secret directly from the target process anyway, right? And that the right thing to do if you want to harden your system is to disallow ptrace-read, and not bother changing software that uses environment variables? Because I thi…

Yes, you can consider all processes running under the same user as able to peek at each other's data. This is the point of running under the same uid: sharing data.One uid should be considered one security domain, with any separators inside it being guardrails, not brick walls.

If you want to prevent other processes from peeking into your process, run it under a different uid. Again. that's the point. A bunch of good software does that, running only small privileged bits in separate processes, and running some / bulk of the processes under an uid with severely limited privileges. See e.g. Postfix MTA, or the typical API server + reverse proxy split.

I don't think that this part of Unix is somehow problematic, or needs changing.

Re: Environment variables are a legacy mess: Let's dive deep into them

#90

Earlier quoted context omitted.

No I meant a property in the application config. For example mbsync/isync does this.

You have a config file, it needs to have secrets so likely you are going to run some templating system where you replace dbpassword: ${dbPassword} with password from some secret system. Hopefuly you understand possible issues with any templating system that could result in replacement failures. String manipulating is one of those "This is easy" until it's not.

Apparently I'm still unclear.

I don't mean to hardcode secrets into the config file either. I was suggesting to put a command into the configuration file that the application then calls to get the secret. This way the secret is only ever passed over a file descriptor between two processes.

Post reply on HN