-
-
Notifications
You must be signed in to change notification settings - Fork 808
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
Security: open call for thoughts on securing WTF's config file #517
Comments
This is interesting. Definitely something to think about. A bit harder since we support multiple file systems, and Something low effort would be just checking file permissions and making sure the file is not readable for anyone except the user (0600 on *nix filesystems), similar to how ssh keys fail. For more security conscious people, we could also support this like a plugin. I've been looking at a program called 'chezmoi' for handling my dot files, largely because of secret management https://github.com/twpayne/chezmoi/blob/master/docs/HOWTO.md#Keep-data-private, and it's methodology seems somewhat appropriate here. |
SSH keys are a good point. This file doesn't likely need to be more secure than anyone's private keys. I like the |
#518 has been merged in. Ensures the default config is chmod |
From a HN comment: "Without that you can't share your configs or have your config in your dotfiles-repository." Not sure I buy the config sharing argument, but the dotfiles repo one is very valid. |
I would also like to see some concept of secrets management; I am not a huge fan of having my API keys just resident in a file on my computer. Maybe if you could specify environment variables in the config, that way a user could use their own secrets management scheme.
And then they can invoke by doing something like:
or
or
Now, does it really matter? That means I'd still have my secret accessible at runtime. I'd have to have my AWS key and secret or whatever else, which would be no different from having in this file. Maybe flexibility is worthwhile for people. |
Since it came up in the discussion on hacker news (https://news.ycombinator.com/item?id=20817101): I have all my config files in a repository (https://github.com/maweki/dotfiles) that I bring out into the system using stow (https://www.gnu.org/software/stow/). I only copy a few password and key files manually to a new pc. All configuration is kept up-to-date through the stow-ed symlinks into the dotfiles repository. This way of handling it makes it impossible to, for example, use the github module as the api key needs to be in that file and I obviously don't want to push the key to my dotfiles repo. I think a good way to handle this would be the way home-assistant does it (https://www.home-assistant.io/docs/configuration/secrets/) where you give secrets with a special prefix and they are loaded from a secrets file. The secrets file can be protected separately using git-secret or any other option to protect/encrypt single files. The goal would be to have no private information in the main configuration file so that it can be shared without modification. |
Someone opened a CVE on the file perms: https://nvd.nist.gov/vuln/detail/CVE-2019-15716 Note that this issue is already fixed in v0.20.0, released last week. |
After first pass, I like the look of how Hass is doing things. Supporting an external |
@mide Modules that take an Here's the GitHub source: https://github.com/wtfutil/wtf/blob/master/modules/github/settings.go#L37 That said, it would be preferable for the user to be able to define the name of their env var and tell WTF what it is, rather than how it is now. |
I like the idea of kubernetes-ish sub-keys as module:
secret1:
env: MY_SECRET
secret2:
file: /keybase/team/myteam/module-secret2
secret3:
cmd: aws secretsmanager get-secret-value --secret-id=module-secret3
secret4: hunter2 |
For API keys, all modules that take an API key setting also support setting that value via env var. The docs for all of them have now been updated to reflect this. Examples: |
Maybe using https://github.com/zalando/go-keyring is an option on desktop OS. |
In #692 I've started the task of creating a secrets file, but am in over my head on Golang programming. collaboration is welcome. |
Anybody watching this issue because they want the feature, take a look at #869 to see if meets your need. Its workable now (modulo docs and that kind of nicety, and I hacked a dozen modules to use it, but not all of them). Feel free to ask any questions in the PR if you run into issues installing the credential management apps, or if I didn't add support to your favorite module, ping me, I will. |
Proposition: why not use backticks also known as as "command substitution". |
It would have to be It is definitely flexible, and doesn't require any module changes. Those are pluses. On the negative side, it is putting a lot of scripting into the user's lap. Also, the scripting isn't portable to Windows (which I don't use, but I feel sympathy for those who do). With the approach in #869, the only thing needed is to add the passwords (using the wtfutil CLI, so no complex scripting), and to delete the existing string from config. And to install the utilities, but that's required with either approach. That said, #869 doesn't in any way prevent adding a feature to the yaml config parser to interpret shell commands as right-side values in yaml, both could exist simultaneously. I'm curious, can you link to relevant secret handling docs for those projects? |
I'm skeptical of having executable shell commands in configuration. Could you point to an example of where this is used to effect? |
Why are you skeptical about it? They all use different methods, but the idea is the same. Backticks is just a proposition, can be use one of the existing approaches. |
Specifying arbitrary commands to provide a password is fairly common, especially with command line tools. Bugwarrior (a utility to fetch actionable items from various sources and pull into the task management system, taskwarrior) allows for specifying passwords directly in the config file, retrieving them from the system keyring, prompting for them at runtime, and evaluating an arbitrary command: https://bugwarrior.readthedocs.io/en/latest/common_configuration.html#password-management Mbsync (a utility to synchronize between a local maildir and remote IMAP server) allows specifying either a password directly in the config file with Another IMAP syncing utility (OfflineImap) allows for sourcing arbitrary python code for its config in general, and referencing those python commands to provide passwords: https://github.com/OfflineIMAP/offlineimap/blob/master/offlineimap.conf#L129 Yet another (GetMail) allows running an arbitrary command to retrieve a password as well: https://wiki.archlinux.org/index.php/Getmail#Password_management As mentioned, Vdirsyncer (which is used to sync CalDAV/CardDAV to a local directory) allows specifying the password in the config file, specifying a command to retrieve it, using the system keyring, and prompting for the password: |
To be clear, skeptical does not mean opposed. It's not something I've seen before. Thanks for the examples @paul-nameless and @zeonin. It's an interesting idea. |
I like the terraform style where the interpolation syntax is: ${} wtf:
password: c3VwZXJzZWNyZXQ=
grid:
columns: [100, 100]
rows: [40, 40]
mods:
weather:
position:
top: 0
left: 0
apiToken: ${password("aGVsbG93b3JsZA==")} Terraform config is using HCL so not sure how nicely this will work with YAML. Alternatively, jinja2 (used by Ansible with YAML) syntax is another option that would look and work in a similar way. |
Slightly tongue-in-cheek answer: systemd More serious, and very relevant answer: AWS's CLI, in obtaining credentials from an 'external process'. For example, mine is |
Just my two cents:: #869 is not a solution to this issue for anyone who doesn't use Docker. I'm sure I'm not the only one who avoids using up resources in abstraction layers unless absolutely needed. |
@alexfornuto Not to pitch it too hard, the field is still open for other solutions, but just to be clear: you do understand that docker does not need to be installed? The only dep is a single binary from https://github.com/docker/docker-credential-helpers/releases (which one depends on your keychain of choice). |
Ahh, I was not aware of that. I've not used that software before, and when I saw Docker I instantly shuddered and didn't look further. |
It is not a solution if you don't want to use macOS keychain etc. though - such as in the example I posted above, the secret is something that already exists elsewhere, so I'd just like to be able to tell wtf how to read it; not duplicate it (and have to keep it in sync if it changes) in a second store. Another option: make it dead simple to configure 'secrets providers', like: secrets-providers:
- name: keychain
command: 'echo "$1" | jq ".Secret"'
- name: keybase
command: 'keybase fs read "/keybase/private/$(keybase whoami)/$1"'
- name: pass
command: 'pass show "$1" | head -n1' Then: foo:
apikey:
secret-provider: keychain / keybase / pass
secret-name: foo-apikey or with some kind of syntactic sugar: foo:
apikey: !SECRET(keychain, foo-apikey) Benefit of this vs. arbitrary 'external commands' inline isn't just de-duplication - it'd allow distributing some common ones with wtf itself, making it easy for people to configure those or just use something if they don't really care, but also allow others to use custom (even proprietary) methods that aren't built-in. |
Note that on mac OS, you can also use If you have immediate desire for pulling keys from keybase, your script only has to satisfy the "get" interface from https://github.com/docker/docker-credential-helpers#development: read the name of the server from stdin, then write a 3-item bit of JSON to stdout. If you wanted to write a full keybase helper in go the credential-helper repo has some utility functions for building such a beast, maybe they'd even accept a contribution, keybase is pretty popular. Who knows what direction it will take post-zoom, though. I wish them well, I use it a bit myself. In the longer term, I think the secret idea is interesting, give it a shot, The current helper approach didn't add any yml config file syntax, so the field is wide open still for some kind of generic shell script config-generation facility, or something more targeted at secrets. |
Another, slightly tangential, thought on this - if the external process could be used anywhere (not just in some special |
The CmdRunner module provides the ability to run any external process and format the output however you like. |
Sure, but that's just for displaying the output, that doesn't allow it to be used for the value of Anyway, it's a tangent, I just thought it was worth mentioning that there could be use cases for 'external process output as config value' beyond just secrets. |
This sounds like an edge case that would add considerable technical and conceptual complexity for very marginal value. This can be accomplished by having a separate config file. This is also unrelated to the security issue. If you want to advocate for this, feel free to open an issue dedicated to it. |
Saw a similar conversation on Twitter, and a saw suggestion of mac keychains. (I am not sure how that works and also specific to macos) |
the helper approach that got merged supports the mac keychain as a store |
What about the simplest approach - multiple config files. Going back to the dotfiles example near the top of this thread, the way this is generally handled is the general dotfiles, most configuration and no private info) are public and then local files, if they exist, are also sourced in at the end of each. For example, the .zshrc file is public, then at the end there's a line like this maybe something like |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
WTF's
config.yml
file is a plain text file stored in the user's home directory. Given the nature of many of the modules in WTF, that file could hold account information, passwords, URIs, and API keys for the user's critical systems.This issue is a place to discuss the security of that file.
The text was updated successfully, but these errors were encountered: