During the development and deployment of an application I come in contact with a number of passwords for local development, testing, staging, code shipment, deployment and monitoring.
The risk involved varies: when I start an application on my local machine admin:password might be sufficient. But what about systems visible in a corporate or public network?
In the early phase of my carrier I learned a lot of Don’ts. But what about the alternatives? I want to present some here.
This Blog post contains best practices to protect password from leaking during development, code sharing, screen sharing, automated testing and deployments.
Even during development we handle application secrets
Password Storage
Don’t: store the passwords in a local file, it might get uploaded or stolen. Don’t write them on paper, it might get copied or lost and typing them by hand limits password length.
Do: I advice you to store passwords in a password manager for the following reasons:
Password length is no issue any more, as they are auto-filled. What about 35 characters?
Password randomness neither. I don’t type them by hand. No idea where to find all the symbols on my keyboard.
Password reusal neither. Whenever you set a password you should always create a new random password… very easy with a password manager.
I personally have good experience with Bitwarden and 1Password. Don’t forget to have an encrypted backup.
Password Sharing
Don’t: Including passwords in internal documentation, mails or similar is risky. They might get stolen, appear on the screen while screen sharing, on pictures and are visible when working in public.
Do: I prefer unshared personal accounts, but in projects some credentials need to be shared, eg. the database user of staging application database or a test user. Our password manager allows sharing passwords within the project team.
Password Mailing
Don’t: Send the password in an unencrypted message, such as mail, SMS, chat message or similar.
Do: How to send passwords to a colleague who has no access to the password manager though. I use Bitwarden Send as follows:
Generate a random password
Create a sharing link with one time access
Send the link to the colleague
Wait until she/he confirms she/he has the password
Create the account or encrypt the data/the shared password with the sent one
Application Configuration
Don’t: commit the passwords with the code into your repository. You cannot delete them anymore. A distant commit still contains them. If you want to open-source the project things only get worse. Passwords might also leak during screen sharing sessions, office pictures or when working in public spaces.
Do: use environment variables to configure the application. At Sandstorm this allows me to deploy an application without ever knowing the production database password. I deploy an app, enable the “with database” option and our Kubernetes operator takes care of the rest. It creates a new database and a new database user, provides the credentials via environment variables to the application and takes care of the daily backups.
Continuous Integration Pipelines
This is similar to the Application: use environment variables and hide the credentials in the project configuration of our e.g. Gitlab. Now you can restrict access to the credentials even further.
Continuous Deployment
As mentioned at Sandstorm we usually do not bother creating a database user by hand. It is part of our automated application deployment. This eliminated the need to share production passwords entirely.
Command Line
Don’t: inlining the password in shell commands shows them on the screen and stores them in the local command history. I want to avoid both.
# do not do this, it exposes your password
my-shell-command --user christoph --password 3j2Dzap1CcT
Do: Usually it is more save to use a password prompt, if the command supports it.
# some commands prompt for a missing password
my-shell-command --user christoph --password
Password:
If this is not feasible you can either use a local file or a local environment variable (if present).
# You can use a local environment variable
my-shell-command --user christoph --password $PASSWORD
# … or file you delete immediatly after
my-shell-command --user christoph --password $(cat pass)
# … or directly paste from the clipboard
# this example is for OS X
my-shell-command --user christoph --password $(pbpaste)
If your password contains special characters by chance, you need to adjust the command a bit.
Secure Shell Connections
I do not need this very often, but it is very handy. Let’s assume you want to migrate data from server A to server B. You can connect to both servers via SSH using your private key. Now you can directly download the data from server A to server B. With the -A flag:
ssh -A server-B.sandstorm.de
# the following commands is executed on server B
scp server-A.sandstorm.de:data.tgz .
For scp the local private key is used for authentication. It does not leave the local machine - or in my case the YubiKey. Nonetheless you should only connect with -A to servers you trust.
As always feedback is highly welcome - and thanks for reading.