Signing back into the Community for the first time? You'll need to reset your password to access your account.  Find out more.

Forum Discussion

XIII's avatar
XIII
Trusted Contributor
3 years ago

How to inject a secret into the environment via a systemd service definition?

I want to inject a secret (password) into the environment for a systemd service, using either Environment= or EnvironmentFile=.

What I tried (and what failed):

1. Environment

Environment=password=$(op read op://Vault/Item/password)

However, since such service is not a script, the password will be set to this literal text; the command itself, not its result...

2. EnvironmentFile

As an override:


[Service]
ExecStartPre=op inject -i /etc/default/myservice.tpl -o /etc/default/myservice
ExecStartPost=rm /etc/default/myservice

with this additional line in etc/default/myservice.tpl:


password=op://Vault/Item/password

However, apparently the environment file is read before executing the ExecStartPre command...

Any tips on how I can inject the password into the environment for this service?


1Password Version: CLI 2.0.0
Extension Version: n/a
OS Version: Raspberry Pi OS Bullseye

  • Former Member's avatar
    Former Member

    Hi XIII ! Another option is to write the secret into a private temp file and read it from there into your app. This is secure because systemd creates private temp files in a separate application-specific namespace. In fact by some accounts it's even more secure than environment variables, which can be queried pretty easily from other processes!

    My suggestion would look like:

    [Service]
    ExecStartPre=/path/to/op read op://Vault/Item/password >/tmp/item
    ExecStart=/some/app # reads file /tmp/item contents into memory as password
    PrivateTmp=yes # Enforces creating /tmp/* in private namespace for the service
    
  • Former Member's avatar
    Former Member

    I am glad you got this working. Is there anything else that we can help with, here?

    Looking forward to hearing from you!

    Best,
    Horia

  • XIII's avatar
    XIII
    Trusted Contributor

    Might be because this service was using this (which is not recommended):


    KillMode=process

    Removed that line (to get the default mode control-group) and that seems to work better (so far).

  • XIII's avatar
    XIII
    Trusted Contributor

    Turns out this does not work as good as I hoped, I always get these errors when I try to restart a service:


    Apr 10 17:06:32 pi systemd[1]: my.service: Found left-over process 1944 (op) in control group while starting unit. Ignoring.
    Apr 10 17:06:32 pi systemd[1]: This usually indicates unclean termination of a previous run, or service implementation deficiencies.

    How to fix this?

  • XIII's avatar
    XIII
    Trusted Contributor

    That's exactly what I (already) did... (and that indeed works!)

    However, this service's ExecStart is pretty complicated; I'd rather not overwrite that (since I manually have to copy the original one each time the author changes it).

  • Former Member's avatar
    Former Member

    Hey XIII, thanks for reaching out to us!

    I think another solution here might be to pass the secret references as environment variables, and to use op run to prefix your ExecStart Command. I played a bit with this with the manual authentication process, hardcoding my session token, and managed to get something like this working:

    [Service]
    User=horia
    Environment="OP_CONFIG_DIR=/home/horia/.config/op"
    Environment="VAR=op://test-vault/docker/username"
    Environment="OP_SESSION_<my_id>=<my_session_token>"
    ExecStart=/usr/bin/op run --no-masking -- bash -c 'echo $VAR'

    I assume this can be ported over to the biometric authentication process as well, but, in case you encounter any hurdles, let us know such that we can take another look, in more detail!

    Best,
    Horia