Recently I was in the situation in which I needed to do some automation involving AWS-Vault, which is a tool for securely managing AWS access keys on developer workstations. Until now I had been using the file backend, which relies on encrypted-at-rest files to store the secrets.

Since there is obviously no caching involved here, every time I wanted to use a secret I would need to type in the passphrase to unlock it, with no cached copy of the passphrase involved. Coupled with a bug that my team faces when applying Terraform (sessions cause remote state S3 bucket reads to fail, worked around with the --no-session option), there was no way that I could create a loop for it.

The solution for this was to move to a different backend. Since I run Linux on my workstation, that meant moving to the secret-service backend, which in my case is backed by gnome-keyring-daemon.

Researching this yielded no solution for how to migrate from one backend to another. There was nothing in a contrib/ directory or any blog posts, so instead I had a dig into the source code. This showed that the AWS-Vault key files (located in $HOME/.awsvault/keys were a base64-encoded blob, that when decoded revealed some JSON content from a standard called JOSE (Javascript Object Signing and Encryption). Specifically, I learned that they contained JWK (Javascript Web Key) attributes, although just trying to decoded it yielded encoding errors:

$ cat .awsvault/keys/mykey |base64 -d
{"alg":"PBES2-HS256+A128KW","created":"2019-12-04 09:33:34.461409668 -0800 PST m=+9.768812157","enc":"A256GCM","p2c":8192,"p2s":"FFFFFFFFFFF"}base64: invalid input

“Perfect, from here on out I can just find a good JOSE library in my language of choice, load it up, and print the payload” was what I thought. This didn’t end up working though. I wasn’t able to figure out a workable method using python-jose, try as I might. My next effort was simply replicate the libraries and methods from the original file in AWS-Vault’s keyring library. This actually ended up working. The final code for this is as follows:

package main

import (
    jose "github.com/dvsekhvalnov/jose2go"
    "fmt"
    "io/ioutil"
    "os"
    "encoding/json"
)

type Item struct {
    Key         string
    Data        []byte
    Label       string
    Description string

    // Backend specific config
    KeychainNotTrustApplication bool
    KeychainNotSynchronizable   bool
}

type Key struct {
    AccessKeyID         string
    SecretAccessKey     string
    SessionToken        string
}

func main() {
    if len(os.Args) != 3 {
       fmt.Println("Wrong input format, expected: ./aws-vault-decrypt <key_file> <password>")
       os.Exit(1)
    }

    bytes, err := ioutil.ReadFile(os.Args[1])
    if os.IsNotExist(err) {
        fmt.Println("File not found")
    }
    if err != nil {
        fmt.Printf("Error: %s", err)
    }

    payload, _, err := jose.Decode(string(bytes), os.Args[2])
    //fmt.Printf(payload)
    var decoded = Item{}
    err = json.Unmarshal([]byte(payload), &decoded)
    var data = Key{}
    err = json.Unmarshal([]byte(decoded.Data), &data)
    fmt.Printf("AWS_ACCESS_KEY_ID: %s\n", string(data.AccessKeyID))
    fmt.Printf("AWS_SECRET_ACCESS_KEY: %s\n", string(data.SecretAccessKey))
}

This resulted in good output:

$ ./aws-vault-decrypt /home/bkero/.awsvault/keys/mykey 'mypassword'
AWS_ACCESS_KEY_ID: AKIAXXXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY: XXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

From here it was simply a matter of setting my new backend in AWS-Vault and running aws-vault add:

$ export AWS_VAULT_BACKEND=secret-service
$ aws-vault add mykey
Enter Access Key ID: AKIAXXXXXXXXXXXXXXXX
Enter Secret Access Key: XXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Added credentials to profile "mykey" in vault

Note that you’ll want to add that export AWS_VAULT_BACKEND=secret-service line to your $HOME/.bashrc if you want the change to be permanent.

Sunset from the malecon in El Rodadero

For the last few days I’ve been spending time in El Rodadero, Colombia before setting off to Palomino for Hackerbeach. Another participant arrived today, and joined me in relaxing before the primary Hackerbeach work in Palomino. It’s peak season here in El Rodadero, which means all the restaurants, the malec√≥n, and the beach are filled to the brim with people, mostly traveling Colombians who come here for what is justifiably one of the most gorgeous beaches in the country.

Continue reading “Hackerbeach Days 1-3”