Sane, safe method to inject top-level secrets?

I’ve been toying around with incus-compose a fair bit this weekend (yay!), and one thing that I have yet to figure out is how to pass secrets into a compose file in a safe and sane way. I am curious to hear what others are doing, because I’m quite sure secrets for container provisioning must be a solved problem by now.

I am a user of passage, a fork of passwordstore.org based on age-encryption.org. So I have cli access to secrets. With the exception of the container I will be provisioning, I want to minimise the exposure of secrets.

Incus-compose (and docker-compose) support both file and environment as a source for a (top-level) secret:

  • reading from a file is not great, because it has to (temporarily) exist (in unencrypted form)
  • reading from an ENV var is not great, because the environment of a running process tends to be inspectable

Your thoughts are much appreciated :slight_smile:

Hey Sagi,

nice you playing with incus-compose, you been one of the first beta testers. Thank you!

My take would be docker secrets + an env you create on execution of incus-compose up.

You need “–os-env” for that to work:

DB_PASSWORD=$(passage ...) incus-compose up --detach --os-env

The secret lands in /run/secrets/<secret-name> with the oci.{u|g}id and an umask of 0o400.

You need “–os-env” for that to work:

DB_PASSWORD=$(passage ...) incus-compose up --detach --os-env

The secret lands in /run/secrets/<secret-name> with the oci.{u|g}id and an umask of 0o400.

If I’m not mistaken, using this method DB_PASSWORD is visible during the duration of the incus-compose run. On Linux via cat /proc/<pid>/environ, and on darwin using ps eww <PID>.

Yes, only on the machine that runs it, not on the incus host.

A workaround would be a incus-compose specific feature:

secrets:
  db-password:
    environment: INVALID_DONT_CARE
    x-incus-compose:
       shell: passage ...

But that allows arbitary shell execution from a maybe shared compose file, I don’t want this.

But that allows arbitary shell execution from a maybe shared compose file, I don’t want this.

yeah, I can see how that would introduce new risks.

Hmm, how about as a cli switch? Something like --env-cmd that interpolates any variables in stdout as if they had been in the environment in the first place?

I like this, can you please also look up other docker compose solutions and write an issue?

If no clean other solution we implement it as you gave it.

Sure. And I am sure there’ll be other users that are more knowledgeable about the container space. This seems rather generic.

I forgot secrets also support secrets.{name}.file also not what you wanted, right?

No, I’d rather keep secrets encrypted at rest, and then decrypted just in time for incus-compose to work.

I like this, can you please also look up other docker compose solutions and write an issue?

At first glance, I’m not very impressed by Docker secrets itself / type:external. It’s basically a tie-in into Docker Swarm. Docker Secrets / Swarm offer encryption at rest and in transit. Incus already offers us encryption in transit of a secret file (which you use). So all that remains is a way to work with password managers people already use.

sops exec-file is a pretty neat approach. It decrypts to a FIFO, thereby limiting to a single read.

I’ll think some more about it.