loading...
Cover image for Simple secret sharing with gopass and summon
Camptocamp Infrastructure Solutions

Simple secret sharing with gopass and summon

raphink profile image Raphaël Pinson ・5 min read

Secrets are a fundamental, yet complex issue in software deployment.

Solutions such as KeepassX are simple to use, but quite impractical when it comes to automation.

More complex options like Hashicorp Vault are extremely powerful, but harder to set up and maintain.

Pass: a simple solution

When it comes to storing securely and sharing passwords in a team, it is hard to come up with a more simple and efficient solution than Git and GnuPG combined.

Pass is a shell script that does just that. Inside a Git repository, Pass stores passwords in individual files encrypted for all private GnuPG keys in the team. It features a CLI to manipulate passwords, add new entries, or search through existing passwords.

More features

However, Pass is quite limited in its features, so another project was born a few years later, to provide a new Go implementation of the Pass standard. Its name: simply Gopass.

Gopass Logo

Installing

Gopass is provided as binaries you can download from the releases page on GitHub.

Features

Here are some of the features that make Gopass a great tool.

Multiple mounts

While pass allows you to have a single Git repository with your passwords, Gopass lets you create multiple repositories called "mounts", which is very useful when you want to share different secrets with different people:

$ gopass mounts
gopass (/home/raphink/.password-store)
├── c2c (/home/raphink/.password-store-c2c)
├── perso (/home/raphink/.password-store-perso)
└── terraform (/home/raphink/.password-store-terraform)

Gopass uses a prefix to access secrets in mounts, so terraform/puppet/c2c actually refers to the secret stored in /home/raphink/.password-store-terraform/puppet/c2c.gpg.

Multiple users

Each Git repository can be set to encrypt passwords for multiple GnuPG keys.

The .gpg-id file at the root of each repository contains the list of public keys to use for encryption, and the .public-keys/ directory keeps a copy of each key, making it easy for collaborators to import them into their keyring before they can start encrypting passwords for the team.

Fuzzy search

Gopass helps you find entries when the key you gave it doesn't match an exact known path:

$ gopass jenkins
[ 0] c2c/c2c_aws/jenkins-c2c
[ 1] c2c/c2c_mgmtsrv/freeipa/c2c-jenkins-swarm
[ 2] c2c/c2c_mgmtsrv/freeipa/jenkins-test-users
[ 3] perso/Devel/jenkins-ci.org
[ 4] terraform/aws/jenkins-c2c

Found secrets - Please select an entry [0]: 

Structured secrets

When decrypting a password, Gopass parses the content into two different parts: a password and a YAML document. For example, the content of a secret could look like this:

foo
---
key1: value1
another_key:
  bar: baz

Password

The first line of the content is the password. If this is all you're interested in, you can use gopass show --password to retrieve it:

$ gopass show --password perso/test
foo

Querying keys

When the second part of the content (lines 2 and following) is a valid YAML document, you can query these values by providing a key, for example:

$ gopass show perso/test key1
value1

Starting with Gopass 1.9.3, you can also query subkeys using either a dot or slash notation:

$ gopass show perso/test another_key.bar
baz
$ gopass show perso/test /another_key/bar
baz

This makes it extremely powerful to store several fields in the same secret.

TOTP

Gopass allows to store TOTP keys alongside passwords. For example, you can have the following secret, stored at terraform/service.io/api:

WPTmU`>b<Y31
---
password: 'WPTmU`>b<Y31'
totp: 'PIJ6AIHETAHSHOO7SHEI1AEK6IH1SOOCHATUOSH8XUAN0OOTH9XAHRUXO4AHJAEVI'
url: https://myservice.io
username: jdoe

In addition to retrieving each field with the corresponding key, you can also generate TOTP tokens with gopass totp:

$ gopass totp terraform/service.io/api
568000 lasts 18s    |------------==================|

Integrations

Gopass can be easily integrated into projects for deployments or CI/CD tasks.

Summon

The easiest way to integrate Gopass is probably to use Summon.

Summon logo

Summon is a tool which dynamically exposes environment variables with values retrieved from various secret stores. gopass is one of its possible providers.

Setup

Setting it up to use gopass is rather straightforward. We use a simple wrapper called summon-gopass, which needs to be in your PATH:

#!/bin/sh
gopass show $(echo "${@}"|tr : \ )

You can also simply make summon-gopass a symbolic link to your gopass binary, but subkeys won't work in this case.

Usage

Summon lets you provide a local secrets.yml file which defines which environment variables you wish to define, and how to find the values.

Here's a simple example of a secrets.yml file using the secret we defined earlier:

SERVICE_URL: !var terraform/service.io/api url
USER: !var terraform/service.io/api username
SERVICE_PASSWORD: !var terraform/service.io/api password

You can test this setup by running the following command in the directory containing secrets.yml:

$ summon env

The output should contain the 3 variables with the values stored in Gopass.

Exposing files

While the format above allows you to expose simple secrets as variables, it is not very practical when you need secrets exposed as files.

Summon covers this need however, using the file flag. For example:

SSH_KEY: !var:file terraform/service.io/ssh private_key

If terraform/service.io/ssh is a secret in Gopass whose private_key YAML field contains an SSH private key, then Summon will extract this secret, place it into a temporary file (in /dev/shm by default) and set the SSH_KEY variable with the path to the file. After the command returns, the temporary file will be delete.

You could then use such a secrets.yml file with:

summon sh -c 'ssh -i $SSH_KEY user@service'

Another useful example is to store a Kubernetes cluster configuration in Gopass, e.g.:

---
apiVersion: v1
clusters:
    - cluster:
        server: https://k8s.example.com
      name: k8s
contexts:
    - context:
        cluster: k8s
        namespace: default
        user: default-cluster-admin
      name: default-admin
current-context: default-admin
kind: Config
preferences: {}
users:
    - name: default-cluster-admin
      user:
        token: averylongtoken

With the following secrets.yml file:

KUBECONFIG: !var:file path/to/secret

You can then work on the Kubernetes cluster with kubectl using:

$ summon kubectl <some command>

Terraform integration

A simple way to pass variables to Terraform is to declare them and use summon to pass the values:

TF_VAR_var1: !var terraform/project1/secret1 field1

You can then run summon terraform to dynamically pass these secrets to Terraform.

Another possibility is to use Camptocamp's Terraform Pass Provider which lets you retrieve and set passwords in Gopass natively in Terraform:

provider "pass" {
  store_dir = "/srv/password-store"    # defaults to $PASSWORD_STORE_DIR
  refresh_store = false                # do not call `git pull`
}

# Store a value into the Gopass store
resource "pass_password" "test" {
  path = "secret/foo"
  password = "0123456789"
  data = {
    zip = "zap"
  }
}

# Retrieve password at another_secret/bar to be used in Terraform code
data "pass_password" "test" {
  path = "another_secret/bar"
}

The provider exposes the secret with the following properties:

  • path: path to the secret
  • password: secret password (first line of the content)
  • data: a structure (map) of the YAML data in the content
  • body: the content found on lines 2 and following, if it could not be parsed as YAML
  • full: the full content (all lines) of the secret

Hiera Integration

The most standard way to store secrets in Hiera is to use hiera-eyaml, which stores secret values encrypted inside YAML files, using either a PKCS7 key (default) or multiple GnuPG keys (when using hiera-eyaml-gpg).

If your passwords are already stored in Gopass, you might want to integrate that into Hiera instead.

The camptocamp/hiera-pass module provides two Hiera backends to retrieve keys either as full Gopass secrets, or as keys inside the secrets.

Posted on by:

raphink profile

Raphaël Pinson

@raphink

Infrastructure Developer & Technology Advocate working @camptocamp.

Camptocamp Infrastructure Solutions

Camptocamp Infrastructure Services — technical blog

Discussion

markdown guide