unicreds

package module
v1.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 11, 2019 License: MIT Imports: 28 Imported by: 0

README

Build Status

unicreds

Unicreds is a command line tool to manage secrets within an AWS account, the aim is to keep securely stored with your systems and data so you don't have to manage them externally. It uses DynamoDB and KMS to store and encrypt these secrets. Access to these keys is controlled using IAM.

Unicreds is written in Go and is based on credstash.

setup

  1. Create a KMS key in IAM, using an aws profile you have configured in the aws CLI. You can ommit --profile if you use the Default profile.
aws --region ap-southeast-2 --profile [yourawsprofile] kms create-key --query 'KeyMetadata.KeyId'

Note: You will also need to assign permission to users other than the root account to access and use the key see How to Help Protect Sensitive Data with AWS KMS. 2. Assign the credstash alias to the key using the key id printed when you created the KMS key.

aws --region ap-southeast-2 --profile [yourawsprofile] kms create-alias --alias-name 'alias/credstash' --target-key-id "xxxx-xxxx-xxxx-xxxx-xxxx"
  1. Run unicreds setup to create the dynamodb table in your region, ensure you have your credentials configured using the awscli.
unicreds setup --region ap-southeast-2 --profile [yourawsprofile]

Note: It is really important to tune DynamoDB to your read and write requirements if you're using unicreds with automation!

demo

To illustrate how unicreds works I made a screen recording of list, put, get and delete.

Image of screencast

usage

usage: unicreds [<flags>] <command> [<args> ...]

A credential/secret storage command line tool.

Flags:
      --help                     Show context-sensitive help (also try --help-long and
                                 --help-man).
  -c, --csv                      Enable csv output for table data.
  -d, --debug                    Enable debug mode.
  -j, --json                     Output results in JSON
  -r, --region=REGION            Configure the AWS region
  -p, --profile=PROFILE          Configure the AWS profile
  -R, --role=ROLE                Specify an AWS role ARN to assume
  -t, --table="credential-store"
                                 DynamoDB table.
  -k, --alias="alias/credstash"  KMS key alias.
  -E, --enc-context=ENC-CONTEXT ...
                                 Add a key value pair to the encryption context.
      --version                  Show application version.

Commands:
  help [<command>...]
    Show help.

  setup
    Setup the dynamodb table used to store credentials.

  get <credential> [<version>]
    Get a credential from the store.

  getall [<flags>]
    Get latest credentials from the store.

  list [<flags>]
    List latest credentials with names and version.

  put <credential> <value> [<version>]
    Put a credential into the store.

  put-file <credential> <value> [<version>]
    Put a credential from a file into the store.

  delete <credential>
    Delete a credential from the store.

  exec <command>...
    Execute a command with all secrets loaded as environment variables.

Unicreds supports the AWS_* environment variables, and configuration in ~/.aws/credentials and ~/.aws/config

examples

  • List secrets using default profile:
$ unicreds list
  • List secrets using the default profile, in a different region:
$ unicreds -r us-east-2 list
$ AWS_REGION=us-east-2 unicreds list
  • List secrets using profile MYPROFILE in ~/.aws/credentials or ~/.aws/config
$ unicreds -r us-west-2 -p MYPROFILE list
$ AWS_PROFILE=MYPROFILE unicreds list
  • List secrets using a profile, but also assuming a role:
$ unicreds -r us-west-2 -p MYPROFILE -R arn:aws:iam::123456789012:role/MYROLE list
  • Store a login for test123 from unicreds using the encryption context feature.
$ unicreds -r us-west-2 put test123 -E 'stack:123' testingsup
   • stored                    name=test123 version=0000000000000000001
  • Retrieve a login for test123 from unicreds using the encryption context feature.
$ unicreds -r us-west-2 get test123 -E 'stack:123'
testingsup
  • Example of a failed encryption context check.
$ unicreds -r us-west-2 get test123 -E 'stack:12'
   ⨯ failed                    error=InvalidCiphertextException:
	status code: 400, request id: 0fed8a0b-5ea1-11e6-b359-fd8168c3c784
  • Execute env command, all secrets are loaded as environment variables.
$ unicreds -r us-west-2 exec -- env

references

install

If you're on OSX you can install unicreds using homebrew now!

brew tap versent/homebrew-taps
brew install unicreds

Otherwise grab an archive from the github releases page.

development

I use scantest to watch my code and run tests on save.

go get github.com/smartystreets/scantest

testing

You can run unit tests which mock out the KMS and DynamoDB backend using make test.

There is an integration test you can run using make integration. You must set the AWS_REGION (default us-west-2), UNICREDS_KEY_ALIAS (default alias/unicreds), and UNICREDS_TABLE_NAME (default credential-store) environment variables to point to valid AWS resources.

auto-versioning

If you've been using unicreds auto-versioning before September 2015, Unicreds had the same bug as credstash when auto-versioning that results in a sorting error after ten versions. You should be able to run the credstash-migrate-autoversion.py script included in the root of the credstash repository to update your versions prior to using the latest version of unicreds.

Docker ENTRYPOINT

It is possible to use unicreds exec as an entrypoint for loading safely your secrets as environment variables inside your container in AWS ECS.

Example
RUN curl -sL \
    https://github.com/Versent/unicreds/releases/download/v1.5.0/unicreds_1.5.0_linux_x86_64.tgz \
 | tar zx -C /usr/local/bin \
 && chmod +x /usr/local/bin/unicreds
ENTRYPOINT ["/usr/local/bin/unicreds", "exec", "--"]

With IAM roles for Amazon ECS tasks you can give the necessary privileges to your container so that it can exploit unicreds.

todo

  • Add the ability to filter list / getall results using DynamoDB filters, at the moment I just use | grep blah.
  • Work on the output layout.
  • Make it easier to import files

license

This code is Copyright (c) 2015 Versent and released under the MIT license. All rights not explicitly granted in the MIT license are reserved. See the included LICENSE.md file for more details.

Documentation

Index

Constants

View Source
const (
	// TableFormatTerm format the table for a terminal session
	TableFormatTerm = iota // 0
	// TableFormatCSV format the table as CSV
	TableFormatCSV // 1
)
View Source
const (
	// DefaultKmsKey default KMS key alias name
	DefaultKmsKey = "alias/credstash"

	// CreatedAtNotAvailable returned to indicate the created at field is missing
	// from the secret/Name
	CreatedAtNotAvailable = "Not Available"
)
View Source
const MaxPaddingLength = 19 // Number of digits in MaxInt64

Variables

View Source
var (

	// ErrSecretNotFound returned when unable to find the specified secret in dynamodb
	ErrSecretNotFound = errors.New("Secret Not Found")

	// ErrHmacValidationFailed returned when the hmac signature validation fails
	ErrHmacValidationFailed = errors.New("Secret HMAC validation failed")

	// ErrTimeout timeout occured waiting for dynamodb table to create
	ErrTimeout = errors.New("Timed out waiting for dynamodb table to become active")
)

Functions

func ComputeHmac256

func ComputeHmac256(message, secret []byte) []byte

ComputeHmac256 compute a hmac256 signature of the supplied message and return the value hex encoded

func Decode

func Decode(data map[string]*dynamodb.AttributeValue, rawVal interface{}) error

Decode decode the supplied struct from the dynamodb result map

func Decrypt

func Decrypt(key, ciphertext []byte) ([]byte, error)

Decrypt AES encryption method which matches the pycrypto package using CTR and AES256. Note this routine seeds the counter/iv with a value of 1 then throws it away?!

func DeleteSecret

func DeleteSecret(tableName *string, name string) error

DeleteSecret delete a secret

func Encode

func Encode(rawVal interface{}) (map[string]*dynamodb.AttributeValue, error)

Encode return the value encoded as a map of dynamo attributes.

func Encrypt

func Encrypt(key, plaintext []byte) ([]byte, error)

Encrypt AES encryption method which matches the pycrypto package using CTR and AES256. Note this routine seeds the counter/iv with a value of 1 then throws it away?!

func GetHighestVersion added in v1.1.0

func GetHighestVersion(tableName *string, name string) (string, error)

GetHighestVersion look up the highest version for a given name

func PaddedInt added in v1.5.0

func PaddedInt(i int) string

PaddedInt returns an integer left-padded with zeroes to the max-int length

func PutSecret

func PutSecret(tableName *string, alias, name, secret, version string, encContext *EncryptionContextValue) error

PutSecret retrieve the secret from dynamodb

func ResolveVersion added in v1.1.0

func ResolveVersion(tableName *string, name string, version int) (string, error)

ResolveVersion converts an integer version to a string, or if a version isn't provided (0), returns "1" if the secret doesn't exist or the latest version plus one (auto-increment) if it does.

func SetAwsConfig added in v1.4.0

func SetAwsConfig(region, profile *string, role *string) (err error)

SetAwsConfig configure the AWS region with a fallback for discovery on EC2 hosts.

func SetDynamoDBConfig added in v1.0.2

func SetDynamoDBConfig(config *aws.Config)

SetDynamoDBConfig override the default aws configuration

func SetDynamoDBSession added in v1.7.0

func SetDynamoDBSession(sess *session.Session)

func SetKMSConfig added in v1.0.2

func SetKMSConfig(config *aws.Config)

SetKMSConfig override the default aws configuration

func SetKMSSession added in v1.7.0

func SetKMSSession(sess *session.Session)

func Setup

func Setup(tableName *string, read *int64, write *int64) (err error)

Setup create the table which stores credentials

Types

type ByName added in v1.2.0

type ByName []*Credential

ByName sort by name

func (ByName) Len added in v1.2.0

func (slice ByName) Len() int

func (ByName) Less added in v1.2.0

func (slice ByName) Less(i, j int) bool

func (ByName) Swap added in v1.2.0

func (slice ByName) Swap(i, j int)

type ByVersion added in v1.1.0

type ByVersion []*Credential

ByVersion sort helper for credentials

func (ByVersion) Len added in v1.1.0

func (a ByVersion) Len() int

func (ByVersion) Less added in v1.1.0

func (a ByVersion) Less(i, j int) bool

func (ByVersion) Swap added in v1.1.0

func (a ByVersion) Swap(i, j int)

type Credential

type Credential struct {
	Name      string `dynamodbav:"name"`
	Version   string `dynamodbav:"version"`
	Key       string `dynamodbav:"key"`
	Contents  string `dynamodbav:"contents"`
	Hmac      []byte `dynamodbav:"hmac"`
	CreatedAt int64  `dynamodbav:"created_at"`
}

Credential managed credential information

func ListSecrets

func ListSecrets(tableName *string, allVersions bool) ([]*Credential, error)

ListSecrets returns a list of all secrets

func (*Credential) CreatedAtDate added in v1.0.3

func (c *Credential) CreatedAtDate() string

CreatedAtDate convert the timestamp field to a date string

type DataKey

type DataKey struct {
	CiphertextBlob []byte
	Plaintext      []byte
}

DataKey which contains the details of the KMS key

func DecryptDataKey

func DecryptDataKey(ciphertext []byte, encContext *EncryptionContextValue) (*DataKey, error)

DecryptDataKey ask kms to decrypt the supplied data key

func GenerateDataKey

func GenerateDataKey(alias string, encContext *EncryptionContextValue, size int) (*DataKey, error)

GenerateDataKey simplified method for generating a datakey with kms

type DecryptedCredential

type DecryptedCredential struct {
	*Credential
	Secret string
}

DecryptedCredential managed credential information

func GetAllSecrets added in v1.1.0

func GetAllSecrets(tableName *string, allVersions bool, encContext *EncryptionContextValue) ([]*DecryptedCredential, error)

GetAllSecrets returns a list of all secrets

func GetHighestVersionSecret added in v1.5.0

func GetHighestVersionSecret(tableName *string, name string, encContext *EncryptionContextValue) (*DecryptedCredential, error)

GetHighestVersionSecret retrieves latest secret from dynamodb using the name

func GetSecret

func GetSecret(tableName *string, name, version string, encContext *EncryptionContextValue) (*DecryptedCredential, error)

GetSecret look up a secret by name and version

type EncryptionContextValue added in v1.4.0

type EncryptionContextValue map[string]*string

EncryptionContextValue key value with helper methods for flag parser

func NewEncryptionContextValue added in v1.4.0

func NewEncryptionContextValue() *EncryptionContextValue

NewEncryptionContextValue create a new encryption context

func (*EncryptionContextValue) IsCumulative added in v1.4.0

func (h *EncryptionContextValue) IsCumulative() bool

IsCumulative flag this value as cumulative

func (*EncryptionContextValue) Set added in v1.4.0

func (h *EncryptionContextValue) Set(value string) error

Set converts a flag value into an encryption context key value

func (*EncryptionContextValue) String added in v1.4.0

func (h *EncryptionContextValue) String() string

type TableWriter

type TableWriter struct {
	// contains filtered or unexported fields
}

TableWriter enables writing of tables in a variety of formats

func NewTable

func NewTable(wr io.Writer) *TableWriter

NewTable create a new table writer

func (*TableWriter) BulkWrite

func (tw *TableWriter) BulkWrite(rows [][]string)

BulkWrite append an array of rows to the buffer

func (*TableWriter) Render

func (tw *TableWriter) Render() error

Render render the table out to the supplied writer

func (*TableWriter) SetFormat

func (tw *TableWriter) SetFormat(tableFormat int)

SetFormat set the format

func (*TableWriter) SetHeaders

func (tw *TableWriter) SetHeaders(headers []string)

SetHeaders set the column headers

func (*TableWriter) Write

func (tw *TableWriter) Write(row []string)

Directories

Path Synopsis
cmd
Code generated by mockery v1.0.0 Code generated by mockery v1.0.0
Code generated by mockery v1.0.0 Code generated by mockery v1.0.0

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL