From 07ebe9c98bea850e4409d918f49a325fb35d7997 Mon Sep 17 00:00:00 2001 From: Jacob Foard Date: Wed, 25 Sep 2019 21:25:43 -0400 Subject: [PATCH] Updating vendor dir Signed-off-by: Jacob Foard --- vendor/go.mozilla.org/sops/.travis.yml | 7 +- vendor/go.mozilla.org/sops/CHANGELOG.rst | 45 +++++ vendor/go.mozilla.org/sops/CODE_OF_CONDUCT.md | 8 + vendor/go.mozilla.org/sops/CONTRIBUTING.md | 5 +- vendor/go.mozilla.org/sops/Dockerfile | 2 +- vendor/go.mozilla.org/sops/Makefile | 7 + vendor/go.mozilla.org/sops/README.rst | 122 +++++++++--- vendor/go.mozilla.org/sops/decrypt/decrypt.go | 4 +- vendor/go.mozilla.org/sops/example.ini | 28 +++ .../sops/keyservice/keyservice.go | 7 +- .../sops/keyservice/keyservice.pb.go | 7 +- .../go.mozilla.org/sops/keyservice/server.go | 34 ++-- vendor/go.mozilla.org/sops/kms/keysource.go | 16 +- vendor/go.mozilla.org/sops/pgp/keysource.go | 19 +- vendor/go.mozilla.org/sops/sops.go | 184 ++++++++++-------- .../sops/stores/dotenv/store.go | 75 ++++--- .../go.mozilla.org/sops/stores/json/store.go | 47 +++-- vendor/go.mozilla.org/sops/stores/stores.go | 82 +++++++- .../go.mozilla.org/sops/stores/yaml/store.go | 77 +++++--- vendor/modules.txt | 2 +- 20 files changed, 563 insertions(+), 215 deletions(-) create mode 100644 vendor/go.mozilla.org/sops/CODE_OF_CONDUCT.md create mode 100644 vendor/go.mozilla.org/sops/example.ini diff --git a/vendor/go.mozilla.org/sops/.travis.yml b/vendor/go.mozilla.org/sops/.travis.yml index 565e54ab..5b5a2ace 100644 --- a/vendor/go.mozilla.org/sops/.travis.yml +++ b/vendor/go.mozilla.org/sops/.travis.yml @@ -1,5 +1,5 @@ language: go -go: 1.9 +go: 1.12 go_import_path: go.mozilla.org/sops/ addons: @@ -15,7 +15,8 @@ before_install: - source ~/.cargo/env script: - - make + - 'if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then make; fi' + - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then make origin-build; fi' - bash <(curl -s https://codecov.io/bash) before_deploy: @@ -27,7 +28,7 @@ before_deploy: - GOOS=linux CGO_ENABLED=0 go build -o dist/sops-${TRAVIS_TAG}.linux go.mozilla.org/sops/cmd/sops - | if [ ! -z "$TRAVIS_TAG" ]; then - version="$(grep '^const version' cmd/sops/version.go |cut -d '"' -f 2)" + version="$(grep '^const Version' version/version.go |cut -d '"' -f 2)" if [ "$version" != "$TRAVIS_TAG" ]; then echo "Git tag $TRAVIS_TAG does not match version $version, update the source!" exit 1 diff --git a/vendor/go.mozilla.org/sops/CHANGELOG.rst b/vendor/go.mozilla.org/sops/CHANGELOG.rst index 6731094e..89a1066f 100644 --- a/vendor/go.mozilla.org/sops/CHANGELOG.rst +++ b/vendor/go.mozilla.org/sops/CHANGELOG.rst @@ -1,6 +1,51 @@ Changelog ========= +3.3.1 +----- + +Bug fixes: + +* Make sure the pgp key fingerprint is longer than 16 characters before + slicing it. (#463) +* Allow for `--set` value to be a string. (#461) + +Project changes: + +* Using `develop` as a staging branch to create releases off of. What + is in `master` is now the current stable release. +* Upgrade to using Go 1.12 to build sops +* Updated all vendored packages + +3.3.0 +----- + +New features: + +* Multi-document support for YAML files +* Support referencing AWS KMS keys by their alias +* Support for INI files +* Support for AWS CLI profiles +* Comment support in .env files +* Added vi to the list of known editors +* Added a way to specify the GPG key server to use through the + SOPS_GPG_KEYSERVER environment variable + +Bug fixes: + +* Now uses $HOME instead of ~ (which didn't work) to find the GPG home +* Fix panic when vim was not available as an editor, but other + alternative editors were +* Fix issue with AWS KMS Encryption Contexts (#445) with more than one + context value failing to decrypt intermittently. Includes an + automatic fix for old files affected by this issue. + +Project infrastructure changes: + +* Added integration tests for AWS KMS +* Added Code of Conduct + + 3.2.0 ----- diff --git a/vendor/go.mozilla.org/sops/CODE_OF_CONDUCT.md b/vendor/go.mozilla.org/sops/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..f0ef43f3 --- /dev/null +++ b/vendor/go.mozilla.org/sops/CODE_OF_CONDUCT.md @@ -0,0 +1,8 @@ +# Community Participation Guidelines + +This repository is governed by Mozilla's code of conduct and etiquette guidelines. +For more details, please read the +[Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). + +## How to Report +For more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page. diff --git a/vendor/go.mozilla.org/sops/CONTRIBUTING.md b/vendor/go.mozilla.org/sops/CONTRIBUTING.md index adedd9c1..07252d07 100644 --- a/vendor/go.mozilla.org/sops/CONTRIBUTING.md +++ b/vendor/go.mozilla.org/sops/CONTRIBUTING.md @@ -4,7 +4,7 @@ Mozilla welcomes contributions from everyone. Here are a few guidelines and inst # Getting started -* Make sure you have Go 1.6 or greater installed. You can find information on how to install Go [here](https://golang.org/dl/) +* Make sure you have Go 1.12 or greater installed. You can find information on how to install Go [here](https://golang.org/dl/) * After following the [Go installation guide](https://golang.org/doc/install), run `go get go.mozilla.org/sops`. This will automatically clone this repository. * Switch into sops's directory, which will be in `$GOPATH/src/go.mozilla.org/sops`. * Run the tests with `make test`. They should all pass. @@ -12,8 +12,9 @@ Mozilla welcomes contributions from everyone. Here are a few guidelines and inst * Add your fork to git's remotes: * If you use SSH authentication: `git remote add git@github.com:/sops.git`. * Otherwise: `git remote add https://github.com//sops.git`. +* **Switch to the `develop` branch: `git checkout develop`** * Make any changes you want to sops, commit them, and push them to your fork. -* Create a pull request, and a contributor will come by and review your code. They may ask for some changes, and hopefully your contribution will be merged to the `master` branch! +* **Create a pull request against `develop`**, and a contributor will come by and review your code. They may ask for some changes, and hopefully your contribution will be merged to the `develop` branch! # Guidelines diff --git a/vendor/go.mozilla.org/sops/Dockerfile b/vendor/go.mozilla.org/sops/Dockerfile index 42a2c996..975e5e5f 100644 --- a/vendor/go.mozilla.org/sops/Dockerfile +++ b/vendor/go.mozilla.org/sops/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.8 +FROM golang:1.12 COPY . /go/src/go.mozilla.org/sops WORKDIR /go/src/go.mozilla.org/sops diff --git a/vendor/go.mozilla.org/sops/Makefile b/vendor/go.mozilla.org/sops/Makefile index 553fe256..99f63435 100644 --- a/vendor/go.mozilla.org/sops/Makefile +++ b/vendor/go.mozilla.org/sops/Makefile @@ -7,6 +7,7 @@ GO := GO15VENDOREXPERIMENT=1 go GOLINT := golint all: test vet generate install functional-tests +origin-build: test vet generate install functional-tests-all install: $(GO) install go.mozilla.org/sops/cmd/sops @@ -40,6 +41,12 @@ functional-tests: $(GO) build -o functional-tests/sops go.mozilla.org/sops/cmd/sops cd functional-tests && cargo test +# Ignored tests are ones that require external services (e.g. AWS KMS) +# TODO: Once `--include-ignored` lands in rust stable, switch to that. +functional-tests-all: + $(GO) build -o functional-tests/sops go.mozilla.org/sops/cmd/sops + cd functional-tests && cargo test && cargo test -- --ignored + deb-pkg: install rm -rf tmppkg mkdir -p tmppkg/usr/local/bin diff --git a/vendor/go.mozilla.org/sops/README.rst b/vendor/go.mozilla.org/sops/README.rst index 19ef3c12..239a5ac4 100644 --- a/vendor/go.mozilla.org/sops/README.rst +++ b/vendor/go.mozilla.org/sops/README.rst @@ -1,7 +1,7 @@ SOPS: Secrets OPerationS ======================== -**sops** is an editor of encrypted files that supports YAML, JSON and BINARY +**sops** is an editor of encrypted files that supports YAML, JSON, ENV, INI and BINARY formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault and PGP. (`demo `_) @@ -24,13 +24,16 @@ Binaries and packages of the latest stable release are available at `https://git Development branch ~~~~~~~~~~~~~~~~~~ -For the adventurous, unstable features are available in the master branch, which you can install with: +For the adventurous, unstable features are available in the `develop` branch, which you can install from source: .. code:: bash $ go get -u go.mozilla.org/sops/cmd/sops + $ cd $GOPATH/src/go.mozilla.org/sops/ + $ git checkout develop + $ make install -(requires Go >= 1.8) +(requires Go >= 1.12) If you don't have Go installed, set it up with: @@ -45,7 +48,7 @@ Or whatever variation of the above fits your system and shell. To use **sops** as a library, take a look at the `decrypt package `_. -**Questions?** ping "ulfr" in ``#security`` on `irc.mozilla.org `_ +**Questions?** ping "ulfr" and "autrilla" in ``#security`` on `irc.mozilla.org `_ (use a web client like `mibbit `_ ). **What happened to Python Sops?** We rewrote Sops in Go to solve a number of @@ -59,6 +62,11 @@ but we strongly recommend you use the Go version instead. Usage ----- +For a quick presentation of Sops, check out this Youtube tutorial: + +.. image:: https://img.youtube.com/vi/V2PRhxphH2w/0.jpg + :target: https://www.youtube.com/watch?v=V2PRhxphH2w + If you're using AWS KMS, create one or multiple master keys in the IAM console and export them, comma separated, in the **SOPS_KMS_ARN** env variable. It is recommended to use at least two master keys in different regions. @@ -210,7 +218,7 @@ And decrypt it using:: $ sops --decrypt test.enc.yaml Encrypting using Azure Key Vault -~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Azure Key Vault integration uses service principals to access secrets in the vault. The following environment variables are used to authenticate: @@ -326,6 +334,23 @@ When removing keys, it is recommended to rotate the data key using ``-r``, otherwise owners of the removed key may have add access to the data key in the past. +KMS AWS Profiles +~~~~~~~~~~~~~~~~ + +If you want to use a specific profile, you can do so with `aws_profile`: + +.. code:: yaml + + sops: + kms: + - arn: arn:aws:kms:us-east-1:656532927350:key/920aff2e-c5f1-4040-943a-047fa387b27e + aws_profile: foo + +If no AWS profile is set, default credentials will be used. + +Similarly the `--aws-profile` flag can be set with the command line with any of the KMS commands. + + Assuming roles and using KMS in various AWS accounts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -392,9 +417,6 @@ to refine the access control of a given KMS master key. When creating a new file, you can specify encryption context in the ``--encryption-context`` flag by comma separated list of key-value pairs: -When creating a new file, you can specify encryption context in the -``--encryption-context`` flag by comma separated list of key-value pairs: - .. code:: bash $ sops --encryption-context Environment:production,Role:web-server test.dev.yaml @@ -449,7 +471,7 @@ Let's take an example: * file named **something.dev.yaml** should use one set of KMS A * file named **something.prod.yaml** should use another set of KMS B * other files use a third set of KMS C -* all live under **mysecretrepo/something.{dev,prod}.yaml** +* all live under **mysecretrepo/something.{dev,prod,gcp}.yaml** Under those circumstances, a file placed at **mysecretrepo/.sops.yaml** can manage the three sets of configurations for the three types of files: @@ -483,7 +505,33 @@ When creating any file under **mysecretrepo**, whether at the root or under a subdirectory, sops will recursively look for a ``.sops.yaml`` file. If one is found, the filename of the file being created is compared with the filename regexes of the configuration file. The first regex that matches is selected, -and its KMS and PGP keys are used to encrypt the file. +and its KMS and PGP keys are used to encrypt the file. It should be noted that +the looking up of ``.sops.yaml`` is from the working directory (CWD) instead of +the directory of the encrypting file (see `Issue 242 `_). + +The path_regex checks the full path of the encrypting file. Here is another example: + +* files located under directory **development** should use one set of KMS A +* files located under directory **production** should use another set of KMS B +* other files use a third set of KMS C + +.. code:: yaml + + creation_rules: + # upon creation of a file under development, + # KMS set A is used + - path_regex: .*/development/.* + kms: 'arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500,arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e+arn:aws:iam::361527076523:role/hiera-sops-prod' + pgp: '1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A' + + # prod files use KMS set B in the PROD IAM + - path_regex: .*/production/.* + kms: 'arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e+arn:aws:iam::361527076523:role/hiera-sops-prod,arn:aws:kms:eu-central-1:361527076523:key/cb1fab90-8d17-42a1-a9d8-334968904f94+arn:aws:iam::361527076523:role/hiera-sops-prod' + pgp: '1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A' + + # other files use KMS set C + - kms: 'arn:aws:kms:us-west-2:927034868273:key/fe86dd69-4132-404c-ab86-4269956b4500,arn:aws:kms:us-west-2:142069644989:key/846cfb17-373d-49b9-8baf-f36b04512e47,arn:aws:kms:us-west-2:361527076523:key/5052f06a-5d3f-489e-b86c-57201e06f31e' + pgp: '1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A' Creating a new file with the right keys is now as simple as @@ -507,6 +555,22 @@ Example: place the following in your ``~/.bashrc`` SOPS_GPG_EXEC = 'your_gpg_client_wrapper' + +Specify a different GPG key server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, ``sops`` uses the key server ``gpg.mozilla.org`` to retrieve the GPG +keys that are not present in the local keyring. +To use a different GPG key server, set the ``SOPS_GPG_KEYSERVER`` environment +variable. + +Example: place the following in your ``~/.bashrc`` + +.. code:: bash + + SOPS_GPG_KEYSERVER = 'gpg.example.com' + + Key groups ~~~~~~~~~~ @@ -734,7 +798,7 @@ YAML and JSON type extensions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``sops`` uses the file extension to decide which encryption method to use on the file -content. ``YAML`` and ``JSON`` files are treated as trees of data, and key/values are +content. ``YAML``, ``JSON``, ``ENV``, and ``INI`` files are treated as trees of data, and key/values are extracted from the files to only encrypt the leaf values. The tree structure is also used to check the integrity of the file. @@ -783,8 +847,9 @@ JSON and TEXT file types do not support anchors and thus have no such limitation YAML Streams ~~~~~~~~~~~~ -``YAML`` supports having more than one document in a single file. ``sops`` does not. For this -reason, the following file won't work in ``sops``: +``YAML`` supports having more than one "document" in a single file, while +formats like ``JSON`` do not. ``sops`` is able to handle both. This means the +following multi-document will be encrypted as expected: .. code:: yaml @@ -793,9 +858,8 @@ reason, the following file won't work in ``sops``: --- data: bar -If you try to encrypt this file with ``sops``, it will ignore all documents except the first, -effectively deleting them. ``sops`` does not support multi-document files, and until our YAML -parser does, it is unlikely it will. +Note that the ``sops`` metadata, i.e. the hash, etc, is computed for the physical +file rather than each internal "document". Top-level arrays ~~~~~~~~~~~~~~~~ @@ -993,6 +1057,10 @@ You can import sops as a module and use it in your python program. tree = sops.walk_and_decrypt(tree, sops_key) sops.write_file(tree, path=path, filetype=pathtype) +Note: this uses the previous implemenation of `sops` written in python, +and so doesn't support newer features such as GCP-KMS. +To use the current version, call out to `sops` using `subprocess.check_output` + Showing diffs in cleartext in git ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1296,28 +1364,18 @@ Mozilla Public License Version 2.0 Authors ------- -By commit count: +The core team is composed of: -* Julien Vehent -* Adrian Utrilla -* Jeremiah Orem -* Rémy HUBSCHER -* Daniel Thorn -* Dick Tang -* Alexis Métaireau -* Brian Hourigan -* Todd Wolfson -* Chris Kolosiwsky -* Boris Kourtoukov -* Elliot Murphy -* Ivan Malopinsky -* Jonathan Barratt +* Adrian Utrilla @autrilla +* Julien Vehent @jvehent +* AJ Banhken @ajvb +And a whole bunch of `contributors `_ Credits ------- -`sops` is inspired by `hiera-eyaml `_, +`sops` was inspired by `hiera-eyaml `_, `credstash `_ , `sneaker `_, `password store `_ and too many years managing diff --git a/vendor/go.mozilla.org/sops/decrypt/decrypt.go b/vendor/go.mozilla.org/sops/decrypt/decrypt.go index 3351459f..c1d110a8 100644 --- a/vendor/go.mozilla.org/sops/decrypt/decrypt.go +++ b/vendor/go.mozilla.org/sops/decrypt/decrypt.go @@ -11,9 +11,9 @@ import ( "go.mozilla.org/sops" "go.mozilla.org/sops/aes" + sopsdotenv "go.mozilla.org/sops/stores/dotenv" sopsjson "go.mozilla.org/sops/stores/json" sopsyaml "go.mozilla.org/sops/stores/yaml" - sopsdotenv "go.mozilla.org/sops/stores/dotenv" ) // File is a wrapper around Data that reads a local encrypted @@ -73,5 +73,5 @@ func Data(data []byte, format string) (cleartext []byte, err error) { return nil, fmt.Errorf("Failed to verify data integrity. expected mac %q, got %q", originalMac, mac) } - return store.EmitPlainFile(tree.Branch) + return store.EmitPlainFile(tree.Branches) } diff --git a/vendor/go.mozilla.org/sops/example.ini b/vendor/go.mozilla.org/sops/example.ini new file mode 100644 index 00000000..e54a166e --- /dev/null +++ b/vendor/go.mozilla.org/sops/example.ini @@ -0,0 +1,28 @@ +; ENC[AES256_GCM,data:40al3asZ8L1+ajzMBp/0sHai9UNP3IoqkLIPNhuuMxs8Cg==,iv:2lqF+4RJTS9wSgjadUEYOyMVbe6eIOOFNIb0jgjdmK8=,tag:PkrPbykEN0ngUhP+ajfLKg==,type:comment] +[name] +firstName = ENC[AES256_GCM,data:30Q/XQ==,iv:nxqUz6dmPjVdXoRrtw/CGOH1HqFYyLmocbfikqzwf9o=,tag:3sIh386PIoTJ3XBu8T2Pww==,type:str] +lastName = ENC[AES256_GCM,data:W1hTh14=,iv:5M3RqShfVjkOatrGj4Z+e6BtOfQK6hZxWdm6IfkwzcY=,tag:zJBc/5O+rELdKu7Ja0IHuQ==,type:str] +age = ENC[AES256_GCM,data:ulhPjA==,iv:0ylri5mup2gAfT3LEyMdoi2orn/hfTvFs0KOzKwN8Ds=,tag:UVuBXcN1vfwbWH9md0K32A==,type:str] + +[address] +city = ENC[AES256_GCM,data:0+RVjaLGpys=,iv:7XomjWqHdmEbUQ4H9RG0L4kpmjnL0ROEP/bj0u9t0io=,tag:Z57atgaPDw1S51H6JfvcGA==,type:str] +postalCode = ENC[AES256_GCM,data:aPMpTW00LR63Zw==,iv:RiTxsg7vYIlaN41O3ESL/IKLwPi5VtsrepN0RdJrRmQ=,tag:gF4W5LmZ9gsrcBXxwrTPrA==,type:str] +state = ENC[AES256_GCM,data:xg8=,iv:6nvhxItys13r39+ktd5wd53T6UmgojeuqRorrM8bPHg=,tag:Osc5sC4LsesS1wZwAUt5tw==,type:str] +streetAddress = ENC[AES256_GCM,data:DXQclrCghMapHiqkow==,iv:aqc0JH4vadJWp9xwF2kch7xYuZ5bYA8yR9L7An6x2q4=,tag:XFj1rCYSSnwZXCh5An0TAA==,type:str] + +[phoneNumbers] +home = ENC[AES256_GCM,data:uD2247keEsbFI0ub,iv:yVWbL4wF6h3FXWMToZJoKy4Unx/Mp7dDbrT8zxJnZtE=,tag:6zR/ufgemmNx5/ySNnD/Aw==,type:str] +office = ENC[AES256_GCM,data:knmFCdTtHhE0pt5q,iv:dYMzj5TX0G3g0ZpGkB+CvR2XEoPDAwu1SSaY1R/sCYM=,tag:52+8cwq7s4Jloit/lYorOA==,type:str] + +[not private] +notsecret_unencrypted = hi there! + +[sops] +lastmodified = 2019-01-11T05:24:42Z +pgp__list_0__map_created_at = 2019-01-11T05:24:42Z +pgp__list_0__map_enc = -----BEGIN PGP MESSAGE-----\n\nwYwDEEVDpnzXnMABBACb46+yRjeFaLKegY3FGypZyE2XXiVUTEEL3iOu/gjN5TOT\n+EzgNKCxT0B+4mhG6/BSkxN6D3iU9D7ABeC2a1OO2I177dH5Mu9vG0RhPmxFQoYC\nyvqW8HnYqy0SnX/BaLrUlAOutFCpnNcwCHrqjX5u2w2f/nq47ZODGp3QbHEDxdLg\nAeT+v1BMYMoCuq5GD5bBeAv04WVv4JjgweEQFuAq4tkaBRDg9eXCIZxGmpuMkYHC\nsPEuuGLX22TrU3Nhq23xMiyTamf0qOCh5FDCZ5M2BMBTtwVneMq0TO/idTFumeFk\nXwA=\n=Lrn7\n-----END PGP MESSAGE----- +unencrypted_suffix = _unencrypted +version = 3.2.0 +pgp__list_0__map_fp = 1022470DE3F0BC54BC6AB62DE05550BC07FB1A0A +mac = ENC[AES256_GCM,data:P0QMbP0PD9zTGUbGw4gdyIXP5/RGOnWqplcXTvJyIYDlZLENNGJTSqb02OpZJ7iCCHi/LfzX0dQ0uacCHVbrgh1uWwgaPlvplJ++WVEpF7CHFplCPj4gvcKk2Jh/tNmQLov1VrfbzdfZf/epkiL1ie15+mG4gYiJEkH6zR24t7k=,iv:YLZu6BIN/8LaYR84m3dNJwMFnmyaZptOhYCH0Hwckrk=,tag:ayAkLDan52fEbliNFbhUGw==,type:str] + diff --git a/vendor/go.mozilla.org/sops/keyservice/keyservice.go b/vendor/go.mozilla.org/sops/keyservice/keyservice.go index 7d426b65..0f9e2747 100644 --- a/vendor/go.mozilla.org/sops/keyservice/keyservice.go +++ b/vendor/go.mozilla.org/sops/keyservice/keyservice.go @@ -41,9 +41,10 @@ func KeyFromMasterKey(mk keys.MasterKey) Key { return Key{ KeyType: &Key_KmsKey{ KmsKey: &KmsKey{ - Arn: mk.Arn, - Role: mk.Role, - Context: ctx, + Arn: mk.Arn, + Role: mk.Role, + Context: ctx, + AwsProfile: mk.AwsProfile, }, }, } diff --git a/vendor/go.mozilla.org/sops/keyservice/keyservice.pb.go b/vendor/go.mozilla.org/sops/keyservice/keyservice.pb.go index b13f7552..d39c654a 100644 --- a/vendor/go.mozilla.org/sops/keyservice/keyservice.pb.go +++ b/vendor/go.mozilla.org/sops/keyservice/keyservice.pb.go @@ -240,9 +240,10 @@ func (m *PgpKey) GetFingerprint() string { } type KmsKey struct { - Arn string `protobuf:"bytes,1,opt,name=arn" json:"arn,omitempty"` - Role string `protobuf:"bytes,2,opt,name=role" json:"role,omitempty"` - Context map[string]string `protobuf:"bytes,3,rep,name=context" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Arn string `protobuf:"bytes,1,opt,name=arn" json:"arn,omitempty"` + Role string `protobuf:"bytes,2,opt,name=role" json:"role,omitempty"` + Context map[string]string `protobuf:"bytes,3,rep,name=context" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + AwsProfile string `protobuf:"bytes,4,opt,name=aws_profile" json:"aws_profile,omitempty"` } func (m *KmsKey) Reset() { *m = KmsKey{} } diff --git a/vendor/go.mozilla.org/sops/keyservice/server.go b/vendor/go.mozilla.org/sops/keyservice/server.go index e4e42b11..b8603fe4 100644 --- a/vendor/go.mozilla.org/sops/keyservice/server.go +++ b/vendor/go.mozilla.org/sops/keyservice/server.go @@ -29,15 +29,7 @@ func (ks *Server) encryptWithPgp(key *PgpKey, plaintext []byte) ([]byte, error) } func (ks *Server) encryptWithKms(key *KmsKey, plaintext []byte) ([]byte, error) { - ctx := make(map[string]*string) - for k, v := range key.Context { - ctx[k] = &v - } - kmsKey := kms.MasterKey{ - Arn: key.Arn, - Role: key.Role, - EncryptionContext: ctx, - } + kmsKey := kmsKeyToMasterKey(key) err := kmsKey.Encrypt(plaintext) if err != nil { return nil, err @@ -77,15 +69,7 @@ func (ks *Server) decryptWithPgp(key *PgpKey, ciphertext []byte) ([]byte, error) } func (ks *Server) decryptWithKms(key *KmsKey, ciphertext []byte) ([]byte, error) { - ctx := make(map[string]*string) - for k, v := range key.Context { - ctx[k] = &v - } - kmsKey := kms.MasterKey{ - Arn: key.Arn, - Role: key.Role, - EncryptionContext: ctx, - } + kmsKey := kmsKeyToMasterKey(key) kmsKey.EncryptedKey = string(ciphertext) plaintext, err := kmsKey.Decrypt() return []byte(plaintext), err @@ -247,3 +231,17 @@ func (ks Server) Decrypt(ctx context.Context, } return response, nil } + +func kmsKeyToMasterKey(key *KmsKey) kms.MasterKey { + ctx := make(map[string]*string) + for k, v := range key.Context { + value := v // Allocate a new string to prevent the pointer below from referring to only the last iteration value + ctx[k] = &value + } + return kms.MasterKey{ + Arn: key.Arn, + Role: key.Role, + EncryptionContext: ctx, + AwsProfile: key.AwsProfile, + } +} diff --git a/vendor/go.mozilla.org/sops/kms/keysource.go b/vendor/go.mozilla.org/sops/kms/keysource.go index b61445d5..9a446179 100644 --- a/vendor/go.mozilla.org/sops/kms/keysource.go +++ b/vendor/go.mozilla.org/sops/kms/keysource.go @@ -42,6 +42,7 @@ type MasterKey struct { EncryptedKey string CreationDate time.Time EncryptionContext map[string]*string + AwsProfile string } // EncryptedDataKey returns the encrypted data key this master key holds @@ -131,7 +132,7 @@ func NewMasterKey(arn string, role string, context map[string]*string) *MasterKe } // NewMasterKeyFromArn takes an ARN string and returns a new MasterKey for that ARN -func NewMasterKeyFromArn(arn string, context map[string]*string) *MasterKey { +func NewMasterKeyFromArn(arn string, context map[string]*string, awsProfile string) *MasterKey { k := &MasterKey{} arn = strings.Replace(arn, " ", "", -1) roleIndex := strings.Index(arn, "+arn:aws:iam::") @@ -143,17 +144,18 @@ func NewMasterKeyFromArn(arn string, context map[string]*string) *MasterKey { } k.EncryptionContext = context k.CreationDate = time.Now().UTC() + k.AwsProfile = awsProfile return k } // MasterKeysFromArnString takes a comma separated list of AWS KMS ARNs and returns a slice of new MasterKeys for those ARNs -func MasterKeysFromArnString(arn string, context map[string]*string) []*MasterKey { +func MasterKeysFromArnString(arn string, context map[string]*string, awsProfile string) []*MasterKey { var keys []*MasterKey if arn == "" { return keys } for _, s := range strings.Split(arn, ",") { - keys = append(keys, NewMasterKeyFromArn(s, context)) + keys = append(keys, NewMasterKeyFromArn(s, context, awsProfile)) } return keys } @@ -180,12 +182,18 @@ func (key MasterKey) createStsSession(config aws.Config, sess *session.Session) } func (key MasterKey) createSession() (*session.Session, error) { - re := regexp.MustCompile(`^arn:aws[\w-]*:kms:(.+):[0-9]+:key/.+$`) + re := regexp.MustCompile(`^arn:aws[\w-]*:kms:(.+):[0-9]+:(key|alias)/.+$`) matches := re.FindStringSubmatch(key.Arn) if matches == nil { return nil, fmt.Errorf("No valid ARN found in %q", key.Arn) } + config := aws.Config{Region: aws.String(matches[1])} + + if key.AwsProfile != "" { + config.Credentials = credentials.NewSharedCredentials("", key.AwsProfile) + } + opts := session.Options{ Config: config, AssumeRoleTokenProvider: stscreds.StdinTokenProvider, diff --git a/vendor/go.mozilla.org/sops/pgp/keysource.go b/vendor/go.mozilla.org/sops/pgp/keysource.go index 8aa9ef94..7ebd7da0 100644 --- a/vendor/go.mozilla.org/sops/pgp/keysource.go +++ b/vendor/go.mozilla.org/sops/pgp/keysource.go @@ -58,6 +58,10 @@ func gpgBinary() string { } func (key *MasterKey) encryptWithGPGBinary(dataKey []byte) error { + fingerprint := key.Fingerprint + if offset := len(fingerprint) - 16; offset > 0 { + fingerprint = fingerprint[offset:] + } args := []string{ "--no-default-recipient", "--yes", @@ -66,7 +70,7 @@ func (key *MasterKey) encryptWithGPGBinary(dataKey []byte) error { "-r", key.Fingerprint, "--trusted-key", - key.Fingerprint[len(key.Fingerprint)-16:], + fingerprint, "--no-encrypt-to", } cmd := exec.Command(gpgBinary(), args...) @@ -99,6 +103,14 @@ func getKeyFromKeyServer(keyserver string, fingerprint string) (openpgp.Entity, return *ents[0], nil } +func gpgKeyServer() string { + keyServer := "gpg.mozilla.org" + if envKeyServer := os.Getenv("SOPS_GPG_KEYSERVER"); envKeyServer != "" { + keyServer = envKeyServer + } + return keyServer +} + func (key *MasterKey) getPubKey() (openpgp.Entity, error) { ring, err := key.pubRing() if err == nil { @@ -108,7 +120,8 @@ func (key *MasterKey) getPubKey() (openpgp.Entity, error) { return entity, nil } } - entity, err := getKeyFromKeyServer("gpg.mozilla.org", key.Fingerprint) + keyServer := gpgKeyServer() + entity, err := getKeyFromKeyServer(keyServer, key.Fingerprint) if err != nil { return openpgp.Entity{}, fmt.Errorf("key with fingerprint %s is not available "+ @@ -246,7 +259,7 @@ func (key *MasterKey) gpgHome() string { if dir == "" { usr, err := user.Current() if err != nil { - return "~/.gnupg" + return path.Join(os.Getenv("HOME"), "/.gnupg") } return path.Join(usr.HomeDir, ".gnupg") } diff --git a/vendor/go.mozilla.org/sops/sops.go b/vendor/go.mozilla.org/sops/sops.go index ee3acb57..69e01dc4 100644 --- a/vendor/go.mozilla.org/sops/sops.go +++ b/vendor/go.mozilla.org/sops/sops.go @@ -100,6 +100,9 @@ type TreeItem struct { // TreeBranch is a branch inside sops's tree. It is a slice of TreeItems and is therefore ordered type TreeBranch []TreeItem +// Trees usually have more than one branch +type TreeBranches []TreeBranch + func valueFromPathAndLeaf(path []interface{}, leaf interface{}) interface{} { switch component := path[0].(type) { case int: @@ -178,8 +181,8 @@ func (branch TreeBranch) Set(path []interface{}, value interface{}) TreeBranch { // Tree is the data structure used by sops to represent documents internally type Tree struct { - Branch TreeBranch Metadata Metadata + Branches TreeBranches // FilePath is the path of the file this struct represents FilePath string } @@ -284,52 +287,62 @@ func (branch TreeBranch) walkBranch(in TreeBranch, path []string, onLeaves func( return in, nil } -// Encrypt walks over the tree and encrypts all values with the provided cipher, except those whose key ends with the UnencryptedSuffix specified on the Metadata struct, or those not ending with EncryptedSuffix, if EncryptedSuffix is provided (by default it is not). -// If encryption is successful, it returns the MAC for the encrypted tree. +// Encrypt walks over the tree and encrypts all values with the provided cipher, +// except those whose key ends with the UnencryptedSuffix specified on the +// Metadata struct, or those not ending with EncryptedSuffix, if EncryptedSuffix +// is provided (by default it is not). If encryption is successful, it returns +// the MAC for the encrypted tree. func (tree Tree) Encrypt(key []byte, cipher Cipher) (string, error) { audit.SubmitEvent(audit.EncryptEvent{ File: tree.FilePath, }) hash := sha512.New() - _, err := tree.Branch.walkBranch(tree.Branch, make([]string, 0), func(in interface{}, path []string) (interface{}, error) { - // Only add to MAC if not a comment - if _, ok := in.(Comment); !ok { - bytes, err := ToBytes(in) - if err != nil { - return nil, fmt.Errorf("Could not convert %s to bytes: %s", in, err) + walk := func(branch TreeBranch) error { + _, err := branch.walkBranch(branch, make([]string, 0), func(in interface{}, path []string) (interface{}, error) { + // Only add to MAC if not a comment + if _, ok := in.(Comment); !ok { + bytes, err := ToBytes(in) + if err != nil { + return nil, fmt.Errorf("Could not convert %s to bytes: %s", in, err) + } + hash.Write(bytes) } - hash.Write(bytes) - } - encrypted := true - if tree.Metadata.UnencryptedSuffix != "" { - for _, v := range path { - if strings.HasSuffix(v, tree.Metadata.UnencryptedSuffix) { - encrypted = false - break + encrypted := true + if tree.Metadata.UnencryptedSuffix != "" { + for _, v := range path { + if strings.HasSuffix(v, tree.Metadata.UnencryptedSuffix) { + encrypted = false + break + } } } - } - if tree.Metadata.EncryptedSuffix != "" { - encrypted = false - for _, v := range path { - if strings.HasSuffix(v, tree.Metadata.EncryptedSuffix) { - encrypted = true - break + if tree.Metadata.EncryptedSuffix != "" { + encrypted = false + for _, v := range path { + if strings.HasSuffix(v, tree.Metadata.EncryptedSuffix) { + encrypted = true + break + } } } - } - if encrypted { - var err error - pathString := strings.Join(path, ":") + ":" - in, err = cipher.Encrypt(in, key, pathString) - if err != nil { - return nil, fmt.Errorf("Could not encrypt value: %s", err) + if encrypted { + var err error + pathString := strings.Join(path, ":") + ":" + in, err = cipher.Encrypt(in, key, pathString) + if err != nil { + return nil, fmt.Errorf("Could not encrypt value: %s", err) + } } + return in, nil + }) + return err + } + + for _, branch := range tree.Branches { + err := walk(branch) + if err != nil { + return "", fmt.Errorf("Error walking tree: %s", err) } - return in, nil - }) - if err != nil { - return "", fmt.Errorf("Error walking tree: %s", err) } return fmt.Sprintf("%X", hash.Sum(nil)), nil } @@ -342,61 +355,67 @@ func (tree Tree) Decrypt(key []byte, cipher Cipher) (string, error) { File: tree.FilePath, }) hash := sha512.New() - _, err := tree.Branch.walkBranch(tree.Branch, make([]string, 0), func(in interface{}, path []string) (interface{}, error) { - encrypted := true - if tree.Metadata.UnencryptedSuffix != "" { - for _, p := range path { - if strings.HasSuffix(p, tree.Metadata.UnencryptedSuffix) { - encrypted = false - break + walk := func(branch TreeBranch) error { + _, err := branch.walkBranch(branch, make([]string, 0), func(in interface{}, path []string) (interface{}, error) { + encrypted := true + if tree.Metadata.UnencryptedSuffix != "" { + for _, p := range path { + if strings.HasSuffix(p, tree.Metadata.UnencryptedSuffix) { + encrypted = false + break + } } } - } - if tree.Metadata.EncryptedSuffix != "" { - encrypted = false - for _, p := range path { - if strings.HasSuffix(p, tree.Metadata.EncryptedSuffix) { - encrypted = true - break + if tree.Metadata.EncryptedSuffix != "" { + encrypted = false + for _, p := range path { + if strings.HasSuffix(p, tree.Metadata.EncryptedSuffix) { + encrypted = true + break + } } } - } - var v interface{} - if encrypted { - var err error - pathString := strings.Join(path, ":") + ":" - if c, ok := in.(Comment); ok { - v, err = cipher.Decrypt(c.Value, key, pathString) - if err != nil { - // Assume the comment was not encrypted in the first place - log.WithField("comment", c.Value). - Warn("Found possibly unencrypted comment in file. " + - "This is to be expected if the file being " + - "decrypted was created with an older version of " + - "SOPS.") - v = c + var v interface{} + if encrypted { + var err error + pathString := strings.Join(path, ":") + ":" + if c, ok := in.(Comment); ok { + v, err = cipher.Decrypt(c.Value, key, pathString) + if err != nil { + // Assume the comment was not encrypted in the first place + log.WithField("comment", c.Value). + Warn("Found possibly unencrypted comment in file. " + + "This is to be expected if the file being " + + "decrypted was created with an older version of " + + "SOPS.") + v = c + } + } else { + v, err = cipher.Decrypt(in.(string), key, pathString) + if err != nil { + return nil, fmt.Errorf("Could not decrypt value: %s", err) + } } } else { - v, err = cipher.Decrypt(in.(string), key, pathString) + v = in + } + // Only add to MAC if not a comment + if _, ok := v.(Comment); !ok { + bytes, err := ToBytes(v) if err != nil { - return nil, fmt.Errorf("Could not decrypt value: %s", err) + return nil, fmt.Errorf("Could not convert %s to bytes: %s", in, err) } + hash.Write(bytes) } - } else { - v = in - } - // Only add to MAC if not a comment - if _, ok := v.(Comment); !ok { - bytes, err := ToBytes(v) - if err != nil { - return nil, fmt.Errorf("Could not convert %s to bytes: %s", in, err) - } - hash.Write(bytes) + return v, nil + }) + return err + } + for _, branch := range tree.Branches { + err := walk(branch) + if err != nil { + return "", fmt.Errorf("Error walking tree: %s", err) } - return v, nil - }) - if err != nil { - return "", fmt.Errorf("Error walking tree: %s", err) } return fmt.Sprintf("%X", hash.Sum(nil)), nil } @@ -451,7 +470,7 @@ type EncryptedFileLoader interface { // way to load unencrypted files into SOPS. Because the files it loads are // unencrypted, the returned data structure does not contain any metadata. type PlainFileLoader interface { - LoadPlainFile(in []byte) (TreeBranch, error) + LoadPlainFile(in []byte) (TreeBranches, error) } // EncryptedFileEmitter is the interface for emitting encrypting files. It provides a @@ -464,13 +483,14 @@ type EncryptedFileEmitter interface { // to emit plain text files from the internal SOPS representation so that they can be // shown type PlainFileEmitter interface { - EmitPlainFile(TreeBranch) ([]byte, error) + EmitPlainFile(TreeBranches) ([]byte, error) } type ValueEmitter interface { EmitValue(interface{}) ([]byte, error) } +// Store is used to interact with files, both encrypted and unencrypted. type Store interface { EncryptedFileLoader PlainFileLoader diff --git a/vendor/go.mozilla.org/sops/stores/dotenv/store.go b/vendor/go.mozilla.org/sops/stores/dotenv/store.go index e268af8b..770e7101 100644 --- a/vendor/go.mozilla.org/sops/stores/dotenv/store.go +++ b/vendor/go.mozilla.org/sops/stores/dotenv/store.go @@ -17,20 +17,26 @@ type Store struct { } func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) { - branch, err := store.LoadPlainFile(in) + branches, err := store.LoadPlainFile(in) if err != nil { return sops.Tree{}, err } var resultBranch sops.TreeBranch mdMap := make(map[string]interface{}) - for _, item := range branch { - s := item.Key.(string) - if strings.HasPrefix(s, SopsPrefix) { - s = s[len(SopsPrefix):] - mdMap[s] = item.Value - } else { + for _, item := range branches[0] { + switch key := item.Key.(type) { + case string: + if strings.HasPrefix(key, SopsPrefix) { + key = key[len(SopsPrefix):] + mdMap[key] = item.Value + } else { + resultBranch = append(resultBranch, item) + } + case sops.Comment: resultBranch = append(resultBranch, item) + default: + panic(fmt.Sprintf("Unexpected type: %T (value %#v)", key, key)) } } @@ -44,28 +50,40 @@ func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) { } return sops.Tree{ - Branch: resultBranch, + Branches: sops.TreeBranches{ + resultBranch, + }, Metadata: internalMetadata, }, nil } -func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranch, error) { +func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) { + var branches sops.TreeBranches var branch sops.TreeBranch for _, line := range bytes.Split(in, []byte("\n")) { if len(line) == 0 { continue } - pos := bytes.Index(line, []byte("=")) - if pos == -1 { - return nil, fmt.Errorf("invalid dotenv input line: %s", line) + if line[0] == '#' { + branch = append(branch, sops.TreeItem{ + Key: sops.Comment{string(line[1:])}, + Value: nil, + }) + } else { + pos := bytes.Index(line, []byte("=")) + if pos == -1 { + return nil, fmt.Errorf("invalid dotenv input line: %s", line) + } + branch = append(branch, sops.TreeItem{ + Key: string(line[:pos]), + Value: string(line[pos+1:]), + }) } - branch = append(branch, sops.TreeItem{ - Key: string(line[:pos]), - Value: string(line[pos+1:]), - }) } - return branch, nil + + branches = append(branches, branch) + return branches, nil } func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) { @@ -78,18 +96,23 @@ func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) { if value == nil { continue } - in.Branch = append(in.Branch, sops.TreeItem{Key: SopsPrefix + key, Value: value}) + in.Branches[0] = append(in.Branches[0], sops.TreeItem{Key: SopsPrefix + key, Value: value}) } - return store.EmitPlainFile(in.Branch) + return store.EmitPlainFile(in.Branches) } -func (store *Store) EmitPlainFile(in sops.TreeBranch) ([]byte, error) { +func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) { buffer := bytes.Buffer{} - for _, item := range in { + for _, item := range in[0] { if isComplexValue(item.Value) { return nil, fmt.Errorf("cannot use complex value in dotenv file: %s", item.Value) } - line := fmt.Sprintf("%s=%s\n", item.Key, item.Value) + var line string + if comment, ok := item.Key.(sops.Comment); ok { + line = fmt.Sprintf("#%s\n", comment.Value) + } else { + line = fmt.Sprintf("%s=%s\n", item.Key, item.Value) + } buffer.WriteString(line) } return buffer.Bytes(), nil @@ -102,6 +125,14 @@ func (Store) EmitValue(v interface{}) ([]byte, error) { return nil, fmt.Errorf("the dotenv store only supports emitting strings, got %T", v) } +func (store *Store) EmitExample() []byte { + bytes, err := store.EmitPlainFile(stores.ExampleFlatTree.Branches) + if err != nil { + panic(err) + } + return bytes +} + func metadataToMap(md stores.Metadata) (map[string]interface{}, error) { var mdMap map[string]interface{} inrec, err := json.Marshal(md) diff --git a/vendor/go.mozilla.org/sops/stores/json/store.go b/vendor/go.mozilla.org/sops/stores/json/store.go index 879bdf1b..10fc46f6 100644 --- a/vendor/go.mozilla.org/sops/stores/json/store.go +++ b/vendor/go.mozilla.org/sops/stores/json/store.go @@ -23,11 +23,13 @@ func (store BinaryStore) LoadEncryptedFile(in []byte) (sops.Tree, error) { return store.store.LoadEncryptedFile(in) } -func (store BinaryStore) LoadPlainFile(in []byte) (sops.TreeBranch, error) { - return sops.TreeBranch{ - sops.TreeItem{ - Key: "data", - Value: string(in), +func (store BinaryStore) LoadPlainFile(in []byte) (sops.TreeBranches, error) { + return sops.TreeBranches{ + sops.TreeBranch{ + sops.TreeItem{ + Key: "data", + Value: string(in), + }, }, }, nil } @@ -36,8 +38,9 @@ func (store BinaryStore) EmitEncryptedFile(in sops.Tree) ([]byte, error) { return store.store.EmitEncryptedFile(in) } -func (store BinaryStore) EmitPlainFile(in sops.TreeBranch) ([]byte, error) { - for _, item := range in { +func (store BinaryStore) EmitPlainFile(in sops.TreeBranches) ([]byte, error) { + // JSON stores a single object per file + for _, item := range in[0] { if item.Key == "data" { return []byte(item.Value.(string)), nil } @@ -49,6 +52,10 @@ func (store BinaryStore) EmitValue(v interface{}) ([]byte, error) { return nil, fmt.Errorf("Binary files are not structured and extracting a single value is not possible") } +func (store BinaryStore) EmitExample() []byte { + return []byte("Welcome to SOPS! Edit this file as you please!") +} + func (store Store) sliceFromJSONDecoder(dec *json.Decoder) ([]interface{}, error) { var slice []interface{} for { @@ -238,21 +245,25 @@ func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) { } } return sops.Tree{ - Branch: branch, + Branches: sops.TreeBranches{ + branch, + }, Metadata: metadata, }, nil } -func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranch, error) { +func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) { branch, err := store.treeBranchFromJSON(in) if err != nil { - return branch, fmt.Errorf("Could not unmarshal input data: %s", err) + return nil, fmt.Errorf("Could not unmarshal input data: %s", err) } - return branch, nil + return sops.TreeBranches{ + branch, + }, nil } func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) { - tree := append(in.Branch, sops.TreeItem{Key: "sops", Value: stores.MetadataFromInternal(in.Metadata)}) + tree := append(in.Branches[0], sops.TreeItem{Key: "sops", Value: stores.MetadataFromInternal(in.Metadata)}) out, err := store.jsonFromTreeBranch(tree) if err != nil { return nil, fmt.Errorf("Error marshaling to json: %s", err) @@ -260,8 +271,8 @@ func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) { return out, nil } -func (store *Store) EmitPlainFile(in sops.TreeBranch) ([]byte, error) { - out, err := store.jsonFromTreeBranch(in) +func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) { + out, err := store.jsonFromTreeBranch(in[0]) if err != nil { return nil, fmt.Errorf("Error marshaling to json: %s", err) } @@ -275,3 +286,11 @@ func (store *Store) EmitValue(v interface{}) ([]byte, error) { } return store.reindentJSON(s) } + +func (store *Store) EmitExample() []byte { + bytes, err := store.EmitPlainFile(stores.ExampleComplexTree.Branches) + if err != nil { + panic(err) + } + return bytes +} diff --git a/vendor/go.mozilla.org/sops/stores/stores.go b/vendor/go.mozilla.org/sops/stores/stores.go index 19d860a4..5d32005a 100644 --- a/vendor/go.mozilla.org/sops/stores/stores.go +++ b/vendor/go.mozilla.org/sops/stores/stores.go @@ -27,7 +27,7 @@ type SopsFile struct { // in the SOPS file by checking for nil. This way we can show the user a // helpful error message indicating that the metadata wasn't found, instead // of showing a cryptic parsing error - Metadata *Metadata `yaml:"sops" json:"sops"` + Metadata *Metadata `yaml:"sops" json:"sops" ini:"sops"` } // Metadata is stored in SOPS encrypted files, and it contains the information necessary to decrypt the file. @@ -67,6 +67,7 @@ type kmskey struct { Context map[string]*string `yaml:"context,omitempty" json:"context,omitempty"` CreatedAt string `yaml:"created_at" json:"created_at"` EncryptedDataKey string `yaml:"enc" json:"enc"` + AwsProfile string `yaml:"aws_profile" json:"aws_profile"` } type gcpkmskey struct { @@ -135,6 +136,7 @@ func kmsKeysFromGroup(group sops.KeyGroup) (keys []kmskey) { EncryptedDataKey: key.EncryptedKey, Context: key.EncryptionContext, Role: key.Role, + AwsProfile: key.AwsProfile, }) } } @@ -265,6 +267,7 @@ func (kmsKey *kmskey) toInternal() (*kms.MasterKey, error) { EncryptedKey: kmsKey.EncryptedDataKey, CreationDate: creationDate, Arn: kmsKey.Arn, + AwsProfile: kmsKey.AwsProfile, }, nil } @@ -305,3 +308,80 @@ func (pgpKey *pgpkey) toInternal() (*pgp.MasterKey, error) { Fingerprint: pgpKey.Fingerprint, }, nil } + +var ExampleComplexTree = sops.Tree{ + Branches: sops.TreeBranches{ + sops.TreeBranch{ + sops.TreeItem{ + Key: "hello", + Value: `Welcome to SOPS! Edit this file as you please!`, + }, + sops.TreeItem{ + Key: "example_key", + Value: "example_value", + }, + sops.TreeItem{ + Key: sops.Comment{Value: " Example comment"}, + Value: nil, + }, + sops.TreeItem{ + Key: "example_array", + Value: []interface{}{ + "example_value1", + "example_value2", + }, + }, + sops.TreeItem{ + Key: "example_number", + Value: 1234.56789, + }, + sops.TreeItem{ + Key: "example_booleans", + Value: []interface{}{true, false}, + }, + }, + }, +} + +var ExampleSimpleTree = sops.Tree{ + Branches: sops.TreeBranches{ + sops.TreeBranch{ + sops.TreeItem{ + Key: "Welcome!", + Value: sops.TreeBranch{ + sops.TreeItem{ + Key: sops.Comment{Value: " This is an example file."}, + Value: nil, + }, + sops.TreeItem{ + Key: "hello", + Value: "Welcome to SOPS! Edit this file as you please!", + }, + sops.TreeItem{ + Key: "example_key", + Value: "example_value", + }, + }, + }, + }, + }, +} + +var ExampleFlatTree = sops.Tree{ + Branches: sops.TreeBranches{ + sops.TreeBranch{ + sops.TreeItem{ + Key: sops.Comment{Value: " This is an example file."}, + Value: nil, + }, + sops.TreeItem{ + Key: "hello", + Value: "Welcome to SOPS! Edit this file as you please!", + }, + sops.TreeItem{ + Key: "example_key", + Value: "example_value", + }, + }, + }, +} diff --git a/vendor/go.mozilla.org/sops/stores/yaml/store.go b/vendor/go.mozilla.org/sops/stores/yaml/store.go index b3045185..bbba2053 100644 --- a/vendor/go.mozilla.org/sops/stores/yaml/store.go +++ b/vendor/go.mozilla.org/sops/stores/yaml/store.go @@ -102,6 +102,10 @@ func (store Store) treeBranchToYamlMap(in sops.TreeBranch) yaml.MapSlice { } func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) { + var data []yaml.MapSlice + if err := (yaml.CommentUnmarshaler{}).UnmarshalDocuments(in, &data); err != nil { + return sops.Tree{}, fmt.Errorf("Error unmarshaling input YAML: %s", err) + } // Because we don't know what fields the input file will have, we have to // load the file in two steps. // First, we load the file's metadata, the structure of which is known. @@ -117,46 +121,63 @@ func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) { if err != nil { return sops.Tree{}, err } - // After that, we load the whole file into a map. - var data yaml.MapSlice - if err := (yaml.CommentUnmarshaler{}).Unmarshal(in, &data); err != nil { - return sops.Tree{}, fmt.Errorf("Error unmarshaling input YAML: %s", err) - } - // Discard metadata, as we already loaded it. - for i, item := range data { - if item.Key == "sops" { - data = append(data[:i], data[i+1:]...) + var branches sops.TreeBranches + for _, doc := range data { + for i, item := range doc { + if item.Key == "sops" { // Erase + doc = append(doc[:i], doc[i+1:]...) + } } + branches = append(branches, store.mapSliceToTreeBranch(doc)) } return sops.Tree{ - Branch: store.mapSliceToTreeBranch(data), + Branches: branches, Metadata: metadata, }, nil } -func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranch, error) { - var data yaml.MapSlice - if err := (yaml.CommentUnmarshaler{}).Unmarshal(in, &data); err != nil { +func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) { + var data []yaml.MapSlice + if err := (yaml.CommentUnmarshaler{}).UnmarshalDocuments(in, &data); err != nil { return nil, fmt.Errorf("Error unmarshaling input YAML: %s", err) } - return store.mapSliceToTreeBranch(data), nil + + var branches sops.TreeBranches + for _, doc := range data { + branches = append(branches, store.mapSliceToTreeBranch(doc)) + } + return branches, nil } func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) { - yamlMap := store.treeBranchToYamlMap(in.Branch) - yamlMap = append(yamlMap, yaml.MapItem{Key: "sops", Value: stores.MetadataFromInternal(in.Metadata)}) - out, err := (&yaml.YAMLMarshaler{Indent: 4}).Marshal(yamlMap) - if err != nil { - return nil, fmt.Errorf("Error marshaling to yaml: %s", err) + out := []byte{} + for i, branch := range in.Branches { + if i > 0 { + out = append(out, "---\n"...) + } + yamlMap := store.treeBranchToYamlMap(branch) + yamlMap = append(yamlMap, yaml.MapItem{Key: "sops", Value: stores.MetadataFromInternal(in.Metadata)}) + tout, err := (&yaml.YAMLMarshaler{Indent: 4}).Marshal(yamlMap) + if err != nil { + return nil, fmt.Errorf("Error marshaling to yaml: %s", err) + } + out = append(out, tout...) } return out, nil } -func (store *Store) EmitPlainFile(in sops.TreeBranch) ([]byte, error) { - yamlMap := store.treeBranchToYamlMap(in) - out, err := (&yaml.YAMLMarshaler{Indent: 4}).Marshal(yamlMap) - if err != nil { - return nil, fmt.Errorf("Error marshaling to yaml: %s", err) +func (store *Store) EmitPlainFile(branches sops.TreeBranches) ([]byte, error) { + var out []byte + for i, branch := range branches { + if i > 0 { + out = append(out, "---\n"...) + } + yamlMap := store.treeBranchToYamlMap(branch) + tmpout, err := (&yaml.YAMLMarshaler{Indent: 4}).Marshal(yamlMap) + if err != nil { + return nil, fmt.Errorf("Error marshaling to yaml: %s", err) + } + out = append(out[:], tmpout[:]...) } return out, nil } @@ -165,3 +186,11 @@ func (store *Store) EmitValue(v interface{}) ([]byte, error) { v = store.treeValueToYamlValue(v) return (&yaml.YAMLMarshaler{Indent: 4}).Marshal(v) } + +func (store *Store) EmitExample() []byte { + bytes, err := store.EmitPlainFile(stores.ExampleComplexTree.Branches) + if err != nil { + panic(err) + } + return bytes +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 55faf761..7ba45a3c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -277,7 +277,7 @@ github.com/zclconf/go-cty/cty/function/stdlib github.com/zclconf/go-cty-yaml # go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a go.mozilla.org/gopgagent -# go.mozilla.org/sops v0.0.0-20181108154941-647d8ed41b61 +# go.mozilla.org/sops v0.0.0-20190611200209-e9e1e87723c8 go.mozilla.org/sops/decrypt go.mozilla.org/sops go.mozilla.org/sops/aes