I recently discovered some new ways to use a tool I’d started with a long time back and subsequently had forgotten pretty much all about. So, now that I’ve learnt some more it’s time to share what I’ve learnt and what I was doing before. Today’s topic is all about managing secrets on your local machine when working on Linux. To be more specific I’m really talking about GNOME based distributions like Ubuntu, and Fedora (default desktops) or any other distribution that has a GNOME based spin. That said, this being Linux, the chances are that you can use these tools on any distribution with a little work or modification.
First, some context of what I was trying to do. I have a few services on remote servers, things like Hashicorp Vault and a self-hosted instance of GitLab that I need to access from my local workstation using the CLI. For those less familiar, these tools often require a Personal Access Token (PAT) to authenticate in place of a password when using multi-factor authentication (MFA). I don’t want to be prompted for these secrets every time I run a command, so I was looking for a way to store these secrets on my machine.
How not to do it
A common pattern that a lot of tools refer to is storing these secrets in environment variables such as VAULT_TOKEN
or GITLAB_TOKEN
. The problem is… where do these variables come from? A common approach to address this is to export
these variables in your shell profile, such as ~/.bashrc
or ~/.zshrc
. This works, but it’s terrible for security as these secrets are now stored in plain text on your machine. This might look like:
# ~/.bashrc
export VAULT_TOKEN="s.123abc456def789"
export GITLAB_TOKEN="890def456abc123"
Not only are they stored in plain text but they are also stored in a file everyone knows about, trivially easy to find and read.
So maybe you’re thinking, “I’ll use some other file that’s not so obvious”. You could use a file like ~/.secrets
or ~/.not_secrets
and source
that file in your shell profile. This is a fraction better, but still not great. This is because the file is still in plain text and still in a location that can be found by simply reading the commonly known shell profile file. This might look like:
# ~/.bashrc
source ~/.secrets
# ~/.secrets
export VAULT_TOKEN="s.123abc456def789"
export GITLAB_TOKEN="890def456abc123"
What I was looking for was a way to store these secrets in a secure way on my machine, and have them accessible in the CLI for commands and scripts.
Enter Keyrings
Bearing mind all this started from Vault , wouldn’t it be useful if we had some local copy of vault to store our secrets? But Vault is rather complicated and cumbersome for a local install and would have exactly the same issue needing a token to access it to get our tokens. So, what if we could use something that’s already on our machine and is designed to store secrets? Enter keyrings. Keyrings are a secure way to store secrets on your machine. They are encrypted and can only be accessed by the user that created them. Tools like keyrings
and gnome-keyring
offer this kind of functionality.
Being that I’m using Fedora, a GNOME based distribution, I have gnome-keyring
installed by default, also as best I could tell from my limited reading before settling for the installed solution it looks like keyrings
might default to storing values in memory for the duration of a session. gnome-keyring
definitely stores values persistently on disk which is what I was looking for, so I got stuck in to gnome-keyring
as my solution, please do your own research with regard to keyrings
if you’re not using a GNOME based distro or want to use a less GNOME specific solution. Also, if you’re on a headless system without a desktop environment some of what we cover here may not be the right solution for you, but for anyone on a GUI workstation, likely based on GNOME, this should be a good solution.
Secure those secrets with gnome-keyring
There is a command line tool for interacting with gnome-keyring
called secret-tool
. This tool allows you to store, retrieve, and delete secrets from your keyring. The basic usage is:
secret-tool store --label="My Secret" key value
The tool will then prompt you for the “password” to be stored.
secret-tool store --label="My Secret" key value
Password:
The first thing that threw me here was this key and value that I needed to pass and what they actually did. My initial thinking was that the key would be similar to the label and the value would be the secret. So you don’t join my confusion this is not the case. The key and value are a unique pair to identify the secret for lookup. So, bearing in mind that we are storing tokens we might decide to call the “key” token
and then the “value” might be the service name, so to store the Vault and GitLab tokens we store the values like this:
$ secret-tool store --label="Vault Token" token vault
Password:
$ secret-tool store --label="GitLab Token" token gitlab
Password:
In both cases we’d pass the actual value of the token to the Password:
prompt.
The --label
flag is optional, but it’s useful for identifying the secret when you want to retrieve it, especially when using the GUI front end to gnome-keyring
which we’ll get to in a moment.
Retrieving secrets with secret-tool
Now that we’ve stored our secrets, we probably need to retrieve them at some point to do something useful with them. To retrieve a secret we need to know the key/token pair that we used to store it. We can then use the secret-tool
command to retrieve the secret:
secret-tool lookup key token
So to retrieve the Vault token we’d use:
secret-tool lookup key vault
This will output the token to the terminal.
$ secret-tool lookup key vault
$ s.123abc456def789
If you want more information about the secret you can use the search
command, again search for the key/token pair:
secret-tool search key token
$ secret-tool search --all key demo-01
[/131]
label = Demo-01
secret = hello blog
created = 2024-04-01 16:02:27
modified = 2024-04-01 16:02:27
schema = org.freedesktop.Secret.Generic
attribute.key = demo-01
Updating and deleting secrets
To update a secret with a new value all you need to do is store the secret again with the same key/token pair. The secret-tool
command will overwrite the existing secret with the new value.
$ secret-tool store --label="Demo-01" key demo-01
Password: # "hello blog"
$ secret-tool lookup key demo-01
hello blog
$ secret-tool store --label="Demo-01" key demo-01
Password: # "Hello Blog"
$ secret-tool lookup key demo-01
Hello Blog
To delete a secret you can use the clear
command:
secret-tool clear key token
$ secret-tool clear key demo-01
Using a secret in a script
OK, great, so we now have a way to store and retrieve secrets on our local machine. But how do we use these secrets in a script?
Well the secret-tool lookup
command is our friend here and we can either use it directly in a script or we can use it to set an environment variable in our shell profile. Directly in a script would minimise the exposure of the secret, but it may be practical to be shared between scripts and/or users so setting an environment variable might be more practical.
In a script it might look like:
#!/bin/bash
local VAULT_TOKEN=$(secret-tool lookup key vault)
In your shell profile it might look like:
# ~/.bashrc
export VAULT_TOKEN=$(secret-tool lookup key vault)
Personally I tend towards the environment variable approach as it’s more flexible for my needs and can be called from any script or command. I also take a number of other precautions to secure my machine and the secrets stored on it, but that’s a topic for another day.
Using the GUI
If you’re not a fan of the command line, or you just want to see what’s in your keyring, you can use the GUI front end to gnome-keyring
. To access the GUI you can use the seahorse
command:
seahorse
You can also find this as “Passwords and Keys” in the GNOME apps; although you may need to install the seahorse
package to get this functionality.
To see this in action let’s quickly create a demo secret using the command line and then view it in the GUI.
$ secret-tool store --label="Demo-01" key demo-01
Password: # "hello blog"
# Prove it's stored by looking it up on the command line
$ secret-tool lookup key demo-01
hello blog
# Open the GUI
$ seahorse # Or navigate to "Passwords and Keys" in the GNOME apps
Once the GUI is open you can search for your secret by the label,hint it’ll most likely be in the “Login” keyring. You can then view the secret by double clicking on it and you’ll end up with something like this:
In the above image we can see 2 secrets stored in the keyring, the first is the Demo-01
secret we just stored and the second is Demo-02
which I stored earlier. I have double clicked on the Demo-01
secret to show the details of the secret. You can see the label, the obscured secret, and the key/token pair that we used to store the secret. You can also copy the value of the secret to the clipboard from here.
What else can you do with gnome-keyring
?
gnome-keyring
is a powerful tool and can be used for more than just storing secrets. You can store SSH keys, GPG keys, and other certificates in your keyring. You can also use the seahorse
GUI to manage these keys.
The function I previously used and really stopped thinking about was that I use ssh-add
a lot to add my SSH keys to the keyring so I don’t have to enter my passphrase every time I use my SSH keys. This is a great feature and I highly recommend using it if you’re not already.
Anything else to note?
One thing to note is that the gnome-keyring
daemon needs to be running for the secret-tool
command to work. This is usually started when you log in to your GNOME session, but if you’re running scripts that use secret-tool
you may need to start the daemon manually. You can do this with the gnome-keyring-daemon
command:
gnome-keyring-daemon
For most users though the daemon will run automatically when you log in to your GNOME session. If you don’t log in to the session with a password, for example you have biometric logins enabled or a smart card, or you’ve set up automatic login, then you may be prompted for a password saying that the keyring is locked. This is because the keyring is locked with your login password and needs to be unlocked before you can access the secrets stored in it. Typically you can just enter your password when prompted soon after logging in and the keyring will be unlocked for the session.
If for some reason it doesn’t unlock automatically you can use the seahorse
GUI to unlock the keyring. You can do this by right clicking on the keyring in the GUI and selecting “Unlock”. You’ll then be prompted for your login password. Or you can use the command line with gnome-keyring-daemon
:
gnome-keyring-daemon --unlock
Or
gnome-keyring-daemon --login
Update: Looking for ways to work with secrets on Windows?
If you’re looking for ways to work with secrets on Windows, check out my post on Managing Secrets in Windows.
Conclusion
So, that’s a quick look at how you can manage secrets on your local machine when working on Linux. I hope you found this useful and that it helps you to secure your secrets on your machine. If you have any questions or comments please feel free to reach out to me on LinkedIn or X / Twitter. Also, please feel free to share this post with anyone you think might find it useful, you’ll find the share buttons below.