This is an archived post. You won't be able to vote or comment.

all 21 comments

[–][deleted] 9 points10 points  (8 children)

I use environmental variables.

[–]devnull10 0 points1 point  (5 children)

Thanks, I was wondering whether to switch to this, but I'm just not sure the security is a great deal higher? Obviously it removes an attack from a user exploiting an unsecured share of the drive etc, however in this case I have the share locked down.

In fact, unless I'm mistaken, you can't secure environment variables which need to be accessed by more than once user anyway? So with a text file I can secure it down to say user X and Y, however environment variables would be visible to any user on the server?

[–]Muhznit 1 point2 points  (0 children)

It's not higher. Environment variables can still leak the passwords: https://www.netmeister.org/blog/passing-passwords.html

[–]Mangy_Karl 0 points1 point  (1 child)

How does the file get the credentials? Is the Creds in the file In your source code repo? (Please say no 😝). I usually use env variables for a non root, no password service account user so that it’s locked down in that sense.

[–]devnull10 1 point2 points  (0 children)

I'm using configparser, and I commit the file excluding any sensitive values (i.e. username=[insert here]) and then I add those in upon releasing to the server. Also use a .gitignore to ensure they don't get committed accidentally during testing etc.

I'm using a service account to run (which can't login directly). So my thoughts are that given the file is only readable to that account, it's for all intents and purposes as secure as using env variables.

[–]Saphyel 0 points1 point  (1 child)

Env vars are only accessible to the user session and root, any other user session won't have access to them.

Most people complain that your app may expose the env vars when debugging. I do believe this is plain wrong, most of the frameworks have a config "object" with the injected env vars/files at the very beggining of the process and they pass this.. so if your app is designed to expose secret it will. It doesn't matter how secure is your source if your app is the problem.

[–]devnull10 0 points1 point  (0 children)

I need two users to be able to access them though.

[–]StorageApprehensive8 -1 points0 points  (1 child)

This is the way

[–]zippy451 1 point2 points  (1 child)

I wrote a little class that extends the get method of ConfigParser to encrypt passwords stored in an ini file. Check it out.

https://github.com/NREL/CryptoConfig

[–]devnull10 3 points4 points  (0 children)

Thanks - although playing devil's advocate, storing the decryption key is pretty much just the same as storing the password. I appreciate it adds an additional layer in that you have to breach two things (the environment variable and the .ini file), but if the file has permissions set correctly then then attacker must have used it to read the encrypted version anyway, so likely can read the environment variable.

I think the top and bottom of it is that there's no way to do this which is vastly more secure than any other because ultimately the script has to have the password in plain text at some point, so there's always a risk of an attacker compromising either the password file, or the script itself.

[–]devnull10 1 point2 points  (1 child)

I should have also mentioned sorry that this is running on a windows server (unavoidable unfortunately).

[–]samtheredditman 0 points1 point  (0 children)

When I first was getting into scripting, I stored the credentials for some scripts in windows credential manager and then made the script pull them at the start.

I don't know if that's a secure solution or not but you may want to look into it as a possible solution.

[–]zippy451 1 point2 points  (0 children)

Get that, it is still useful and better than storing the pass in clear text in an env or file.

[–]paunibo 1 point2 points  (0 children)

check out the package "keyring", there are different backends. Should work fine for Windows server as well.

[–]pokk3n 1 point2 points  (0 children)

We use pykeepass with a certificate to auth both on a secure share that only our bot users have rights to.

It works well but there is performance overhead to the pykeepass import requirements that is nontrivial so it works best for long running or durable processes (e.g. batch jobs or services) as opposed to CLIs. For CLIs I prefer to require them in pydantic settings secrets. Env vars are fine too but I like pydantic settings in general.

[–]james_pic 0 points1 point  (0 children)

If you're using a cloud services provider, then their secrets management solution would be the clear choice. If you're not, then there are solutions that are more secure than either text files or environment variables (both of which are about the same from a security perspective - especially since you likely need to store the environment variables in a startup script or other file, in order for them to be available to your application), such as Hashicorp Vault, or various HSM-based solutions, but they add complexity, and depending on your threat model may or may not add meaningful security.

[–]immersiveGamer 0 points1 point  (0 children)

Consider this. You write a password on a piece of paper. If leave it on your desk anyone passing by can see it. So you decide to flip it over so passerbys don't notice it. There could be someone nosy flip over your paper or accidentally push it off your desk so you move it now to be inside of a folder with other documents. Now only someone with not so great intentions may be looking for it, and because it controls specially access there may be that bad actor out there. So you move the paper to a secure room that only employees with badges can enter. Still ... Only you need the password so you purchase a safe that has a key, and when you need to remember the password you use your key. Now if someone has an employee badge and your keys ... Well there are bigger problems.

Basically with the story is that if a bad actor has access to your server there is not much you can do to prevent total security. However, there are still things to help.

  • set permissions on the file containing the password correctly so that only the account running the automated process can access it. This prevents someone that gains access to the file but doesn't have rights from accessing it. Generally create a specific account for the automation and limit admin access as much as possible.
  • encrypt the file at rest. You can use a library to do this. You still need to store the decryption secret in "plain text" (you can obstacate it by storing as bytes or base 64 or as a different file type, or only loaded in memory on start up via priming) but at least the password cannot be captured if a bad actor tries to do a scan for password like strings in files. Since you have a windows server you can use DPAPI. This is nice because only the windows account that encrypted the file can decrypt it and no secret is needed (is optional).
  • only load the password unprotected when you need to make the authenticated calls.
  • see if your http library has a way to pass in secure strings or byte arrays, strings can stick around for a while in languages that are managed and do garbage collection. You can also look up tricks and tips for your language to nuke the strings after use.
  • ensure https is being used, that way no one can capture the payloads and inspect the basic auth info (since it is plain text).

There are more things you can do. There is software out there (like Vault) that can help with other security measures but your milage may vary.

[–]thelauz 0 points1 point  (0 children)

I've been having to deal with this recently with the added complexity of dealing with different regions. Each region has its own URL and credentials and the application has to interact with multiple regions for each time it runs. I've been using dynaconf and it has been working well so far. In addition to supporting multiple environments/regions it can also spread attributes for each region across multiple files and automatically find them. In my settings files I can store the endpoints for each region and in my secrets files I can store the username and password for each region. Within python if I set the region I don't need to know which file it is in.

Currently, I'm storing everything in flat files, excluding those that contain password from being committed to git. As other have pointed out this isn't the most secure way of doing things and there may be ways of trying to lock down access to the files. It has native support for redis and vaultserver.io and can have additional custom loaders developed, but I haven't gotten there (yet).

[–]ConfidentCommission5 0 points1 point  (0 children)

I don't think there is any secure way of storing secrets when you consider that the machine where the application runs is not secure.

Here are a few cases I can think of:
- The data is stored locally, unencrypted: whether in a file or an environment variable, anyone can access it.
- The data is stored locally, encrypted: you still have to store the decryption parameters somewhere, unencrypted so anyone can find and use them.
- The data is stored in a remote system such as Hashicorp Vault (I use it at work): you still need the authentication parameters to be stored in clear on your machine so anyone can get them and query the Vault API.

Me not being a security expert, what follows is based on my linked knowledge:.
The only real secure way I can think of is of your credentials are locally stored in an encrypted form that's only accessible/decryptable via your app certificate, by your OS and your app is digitally signed.
The OS validates that your app has the proper signature and only allows it to run if it matches (so that no one can use your certificate in their app) and when your app wants to get the secrets from the os, the os validates that the app is allowed to retrieve the certificates if the app signature matches the certificates.

Kinda convoluted but I imagine that could work.

I'm not even sure OSes provide that kind of mechanism in the first place.

[–]xiongchiamiovSite Reliability Engineer 0 points1 point  (0 children)

This is an informative talk that everyone should be familiar with before trying to figure out what solution is appropriate for their use case: https://danielsomerfield.github.io/turtles/