Keeping passwords out

Most development projects rely on protected, external resources, such as databases, or rest services; and many times, for the sake of simplified testing, we add those credentials to our configuration files, which, if accidentally leaks to the wrong person, can become a painful and expensive issue.

In this article, I will demonstrate how to avoid these issues in a Java, Maven development environment.

Password leaks can be avoided by simply keeping your passwords out of version controlled configuration files, that are part of your project.

First off — never commit your target/ directory. Most tools initialize .gitignore with the target directory omitted from the project. Always verify that this folder is ignored in whatever version control tool is being used.

In maven, you can maintain these in the <properties> section of your ~/.m2/settings.xml, and the property files in your project will simply reference the ${property.value} when building and testing.

The problem with storing these settings in your settings.xml, is that you have to find a secure channel to share with other members of your team; and if the password is updated or changed, you have to re-share the new password to team members.

Next, short coming with using settings.xml, is providing these passwords to a CD/CI automated build pipeline. It’s not impossible to securely share the file, but a secure custom solution will need to be derived.

The solution that I prefer, is to use a password vault of some sort. There are many secure services available for use, such as: AWS Secrets Manager, Hashicorp Vault, LastPass, Credstash, etc. and the one that best fits your environment should be chosen.

All of these tools provide the ability to access passwords from a command line interface, making them suitable for storing, sharing, and using passwords at build time of your project.

In the case of a CD/CI in AWS, a password manager that integrates with AWS IAM roles will be most suitable.

Prerequisites

Typical Configuration File

conf.acs.db.username=alfresco
conf.acs.db.password=${acs.db.password}

Typical POM File with Resource Filtering

 <resources>
      <resource>
        <directory>src/main/resources/properties</directory>
        <filtering>true</filtering>
      </resource>
</resources>

Using AWS Secrets Manager

Secrets can be stored for a monthly cost per secret using AWS Secret Manager.

To store a password, you simply invoke the following command with the password, or binary file that you want to protect. In addition, I would use the optional KMS encryption key id on the secret, and grant access to additional users or roles who should also be able to access the password.

alex@mbp:~$ aws secretsmanager create-secret --name alfresco.env.acs.db.password --kms-key-id f51eeaab-1f1a-499d-8f36-ce5a744d8537 --secret-string mypAs5w0rd
{
    "VersionId": "cef078f2-ed73-425c-823c-6e486ece4317",
    "Name": "alfresco.env.acs.db.password",
    "ARN": "arn:aws:secretsmanager:us-east-1:760790457133:secret:alfresco.env.acs.db.password-DVHl4x"
}

Then Building your project using AWS Secrets Manager:

mvn install -Dacs.db.password=$(aws secretsmanager get-secret-value --secret-id alfresco.env.acs.db.password  |jq -r .SecretString)

The command to fetch your password for building should be wrapped into a small shell script or even alias, for shorter build command.

The outcome of the fetch password command is as follows:

alex@mbp:~$ aws secretsmanager get-secret-value --secret-id alfresco.env.acs.db.password  |jq -r .SecretString
mypAs5w0rd

Using LastPass

lpass login --trust mylastpass@emailaddress

Next Add your credentials/secret using the lastpass UI

Then using the lastpass CLI you can retrieve this password for use in your build command

mvn install -Dacs.db.password=$(lpass show Alex/dev-database |yq -r .Password) -Ddb.username=$(lpass show Alex/dev-database |yq -r .Username)

The results of the lpass command looks like this:


alex@mbp:~$ lpass show Alex/dev-database |yq .
{
  "Alex/dev-database [id": "932803627798321243]",
  "Username": "alfresco",
  "Password": "GEE474*Tjus6",
  "Alias": null,
  "SID": null,
  "Database": "alfresco",
  "Port": 5432,
  "Hostname": "dev-db.dev",
  "Type": "postgresql",
  "NoteType": "Database"
}


For creating passwords, both tools also provide a utility for generating random passwords of different strengths and lengths that I highly recommend for generating the passwords you use to protect your service accounts, and even your own user account.

Using Hashicorp Vault

Using Vault is also very simple

vault kv put secret/password value=mypassword

mvn install -Dacs.db.password=$(vault kv get -format json  secret/password |jq -r ".data.value")

The response for Vault password looks like this:

# Output
{
  "request_id": "239272e5-abe8-c2af-93f9-655e718141f6",
  "lease_id": "",
  "lease_duration": 604800,
  "renewable": false,
  "data": {
    "value": "mypassword"
  },
  "warnings": null
}

For using Hashicorp Vault, you will need access to hosted service. My previous blog post explains how to deploy a containerized version of Vault.

Using Credstash

Credstash is an Open Source project built to be used against AWS dynamodb with KMS Key encryption.

credstash put -k kms-key-id acs.env.db.password mydbpassword

mvn install -Dacs.db.password=$(credstash get acs.env.db.password)

Leave a comment