From cba61b6444be15c3c3c0607c36e81993a1bc11b2 Mon Sep 17 00:00:00 2001 From: Nina Garcia Date: Tue, 8 Sep 2020 13:07:58 -0700 Subject: [PATCH 01/40] Update README.rst Edit: unencrypted prefix -> unencrypted suffix --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 864e87240..702ab6c16 100644 --- a/README.rst +++ b/README.rst @@ -1403,7 +1403,7 @@ By default, ``sops`` encrypts all the values of a YAML or JSON file and leaves t keys in cleartext. In some instances, you may want to exclude some values from being encrypted. This can be accomplished by adding the suffix **_unencrypted** to any key of a file. When set, all values underneath the key that set the -**_unencrypted** prefix will be left in cleartext. +**_unencrypted** suffix will be left in cleartext. Note that, while in cleartext, unencrypted content is still added to the checksum of the file, and thus cannot be modified outside of sops without From e8d00046e1630dede664ebf9ebcd88d4fba59167 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sat, 4 Jul 2020 10:47:06 -0700 Subject: [PATCH 02/40] Add support for age. --- age/keysource.go | 183 ++++++ cmd/sops/main.go | 63 +- go.mod | 10 +- go.sum | 42 +- keyservice/keyservice.go | 9 + keyservice/keyservice.pb.go | 1189 +++++++++++++++++++++++------------ keyservice/keyservice.proto | 5 + keyservice/server.go | 40 ++ stores/stores.go | 45 +- 9 files changed, 1164 insertions(+), 422 deletions(-) create mode 100644 age/keysource.go diff --git a/age/keysource.go b/age/keysource.go new file mode 100644 index 000000000..063b7225c --- /dev/null +++ b/age/keysource.go @@ -0,0 +1,183 @@ +package age + +import ( + "bufio" + "bytes" + "fmt" + "io" + "os" + "strings" + + "filippo.io/age" +) + +// MasterKey is an age key used to encrypt and decrypt sops' data key. +type MasterKey struct { + Identity string // a Bech32-encoded private key + Recipient string // a Bech32-encoded public key + EncryptedKey string // a sops data key encrypted with age + + parsedIdentity *age.X25519Identity // a parsed age private key + parsedRecipient *age.X25519Recipient // a parsed age public key +} + +// Encrypt takes a sops data key, encrypts it with age and stores the result in the EncryptedKey field. +func (key *MasterKey) Encrypt(datakey []byte) error { + buffer := &bytes.Buffer{} + + if key.parsedRecipient == nil { + parsedRecipient, err := age.ParseX25519Recipient(key.Recipient) + + if err != nil { + return fmt.Errorf("failed to parse input as Bech32-encoded age public key: %v", err) + } + + key.parsedRecipient = parsedRecipient + } + + w, err := age.Encrypt(buffer, key.parsedRecipient) + + if err != nil { + return fmt.Errorf("failed to open file for encrypting sops data key with age: %v", err) + } + + if _, err := w.Write(datakey); err != nil { + return fmt.Errorf("failed to encrypt sops data key with age: %v", err) + } + + if err := w.Close(); err != nil { + return fmt.Errorf("failed to close file for encrypting sops data key with age: %v", err) + } + + key.EncryptedKey = buffer.String() + + return nil +} + +// EncryptIfNeeded encrypts the provided sops' data key and encrypts it if it hasn't been encrypted yet. +func (key *MasterKey) EncryptIfNeeded(datakey []byte) error { + if key.EncryptedKey == "" { + return key.Encrypt(datakey) + } + + return nil +} + +// EncryptedDataKey returns the encrypted data key this master key holds. +func (key *MasterKey) EncryptedDataKey() []byte { + return []byte(key.EncryptedKey) +} + +// SetEncryptedDataKey sets the encrypted data key for this master key. +func (key *MasterKey) SetEncryptedDataKey(enc []byte) { + key.EncryptedKey = string(enc) +} + +// Decrypt decrypts the EncryptedKey field with the age identity and returns the result. +func (key *MasterKey) Decrypt() ([]byte, error) { + path := fmt.Sprintf("%s/.sops/age/%s.key", os.Getenv("HOME"), key.Recipient) + + _, err := os.Stat(path) + + if os.IsNotExist(err) { + return nil, fmt.Errorf("no private key found at %s", path) + } + + file, err := os.Open(path) + + defer file.Close() + + scanner := bufio.NewScanner(file) + + var privateKey string + + for scanner.Scan() { + line := scanner.Text() + + if strings.HasPrefix(line, "AGE-SECRET-KEY") { + privateKey = line + break + } + } + + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error scanning lines in age private key file: %v", err) + } + + if privateKey == "" { + return nil, fmt.Errorf("no age private key found in file at: %v", path) + } + + parsedIdentity, err := age.ParseX25519Identity(string(privateKey)) + + if err != nil { + return nil, fmt.Errorf("failed to parse private key as age X25519Identity at %s: %v", path, err) + } + + buffer := &bytes.Buffer{} + reader := bytes.NewReader([]byte(key.EncryptedKey)) + + r, err := age.Decrypt(reader, parsedIdentity) + + if err != nil { + return nil, fmt.Errorf("failed to open encrypted data key: %v", err) + } + + if _, err := io.Copy(buffer, r); err != nil { + return nil, fmt.Errorf("failed to read encrypted data key: %v", err) + } + + return buffer.Bytes(), nil +} + +// NeedsRotation returns whether the data key needs to be rotated or not. +func (key *MasterKey) NeedsRotation() bool { + return false +} + +// ToString converts the key to a string representation. +func (key *MasterKey) ToString() string { + return key.Recipient +} + +// ToMap converts the MasterKey to a map for serialization purposes. +func (key *MasterKey) ToMap() map[string]interface{} { + out := make(map[string]interface{}) + out["recipient"] = key.Recipient + out["enc"] = key.EncryptedKey + return out +} + +// MasterKeysFromRecipients takes a comma-separated list of Bech32-encoded public keys and returns a +// slice of new MasterKeys. +func MasterKeysFromRecipients(commaSeparatedRecipients string) ([]*MasterKey, error) { + recipients := strings.Split(commaSeparatedRecipients, ",") + + var keys []*MasterKey + + for _, recipient := range recipients { + key, err := MasterKeyFromRecipient(recipient) + + if err != nil { + return nil, err + } + + keys = append(keys, key) + } + + return keys, nil +} + +// MasterKeyFromRecipient takes a Bech32-encoded public key and returns a new MasterKey. +func MasterKeyFromRecipient(recipient string) (*MasterKey, error) { + parsedRecipient, err := age.ParseX25519Recipient(recipient) + + if err != nil { + return nil, err + } + + return &MasterKey{ + Recipient: recipient, + parsedRecipient: parsedRecipient, + }, nil +} diff --git a/cmd/sops/main.go b/cmd/sops/main.go index e99733d8e..11a2ddfc6 100644 --- a/cmd/sops/main.go +++ b/cmd/sops/main.go @@ -16,6 +16,7 @@ import ( "github.com/sirupsen/logrus" "go.mozilla.org/sops/v3" "go.mozilla.org/sops/v3/aes" + "go.mozilla.org/sops/v3/age" _ "go.mozilla.org/sops/v3/audit" "go.mozilla.org/sops/v3/azkv" "go.mozilla.org/sops/v3/cmd/sops/codes" @@ -61,7 +62,7 @@ func main() { }, } app.Name = "sops" - app.Usage = "sops - encrypted file editor with AWS KMS, GCP KMS, Azure Key Vault and GPG support" + app.Usage = "sops - encrypted file editor with AWS KMS, GCP KMS, Azure Key Vault, age, and GPG support" app.ArgsUsage = "sops [options] file" app.Version = version.Version app.Authors = []cli.Author{ @@ -96,6 +97,9 @@ func main() { https://docs.microsoft.com/en-us/go/azure/azure-sdk-go-authorization#use-environment-based-authentication. The user/sp needs the key/encrypt and key/decrypt permissions) + To encrypt or decrypt using age, specify the recipient in the -a flag, or + in the SOPS_AGE_RECIPIENTS environment variable. + To encrypt or decrypt using PGP, specify the PGP fingerprint in the -p flag or in the SOPS_PGP_FP environment variable. @@ -377,6 +381,10 @@ func main() { Name: "hc-vault-transit", Usage: "the full vault path to the key used to encrypt/decrypt. Make you choose and configure a key with encrption/decryption enabled (e.g. 'https://vault.example.org:8200/v1/transit/keys/dev'). Can be specified more than once", }, + cli.StringSliceFlag{ + Name: "age", + Usage: "the age recipient the new group should contain. Can be specified more than once", + }, cli.BoolFlag{ Name: "in-place, i", Usage: "write output back to the same file instead of stdout", @@ -396,6 +404,7 @@ func main() { gcpKmses := c.StringSlice("gcp-kms") vaultURIs := c.StringSlice("hc-vault-transit") azkvs := c.StringSlice("azure-kv") + ageRecipients := c.StringSlice("age") var group sops.KeyGroup for _, fp := range pgpFps { group = append(group, pgp.NewMasterKeyFromFingerprint(fp)) @@ -422,6 +431,14 @@ func main() { } group = append(group, k) } + for _, recipient := range ageRecipients { + k, err := age.MasterKeyFromRecipient(recipient) + if err != nil { + log.WithError(err).Error("Failed to add key") + continue + } + group = append(group, k) + } return groups.Add(groups.AddOpts{ InputPath: c.String("file"), InPlace: c.Bool("in-place"), @@ -552,6 +569,11 @@ func main() { Usage: "comma separated list of PGP fingerprints", EnvVar: "SOPS_PGP_FP", }, + cli.StringFlag{ + Name: "age, a", + Usage: "comma separated list of age recipients", + EnvVar: "SOPS_AGE_RECIPIENTS", + }, cli.BoolFlag{ Name: "in-place, i", Usage: "write output back to the same file instead of stdout", @@ -604,6 +626,14 @@ func main() { Name: "rm-hc-vault-transit", Usage: "remove the provided comma-separated list of Vault's URI key from the list of master keys on the given file ( eg. https://vault.example.org:8200/v1/transit/keys/dev)", }, + cli.StringFlag{ + Name: "add-age", + Usage: "add the provided comma-separated list of age recipients fingerprints to the list of master keys on the given file", + }, + cli.StringFlag{ + Name: "rm-age", + Usage: "remove the provided comma-separated list of age recipients from the list of master keys on the given file", + }, cli.StringFlag{ Name: "add-pgp", Usage: "add the provided comma-separated list of PGP fingerprints to the list of master keys on the given file", @@ -673,8 +703,8 @@ func main() { return toExitError(err) } if _, err := os.Stat(fileName); os.IsNotExist(err) { - if c.String("add-kms") != "" || c.String("add-pgp") != "" || c.String("add-gcp-kms") != "" || c.String("add-hc-vault-transit") != "" || c.String("add-azure-kv") != "" || - c.String("rm-kms") != "" || c.String("rm-pgp") != "" || c.String("rm-gcp-kms") != "" || c.String("rm-hc-vault-transit") != "" || c.String("rm-azure-kv") != "" { + if c.String("add-kms") != "" || c.String("add-pgp") != "" || c.String("add-gcp-kms") != "" || c.String("add-hc-vault-transit") != "" || c.String("add-azure-kv") != "" || c.String("add-age") != "" || + c.String("rm-kms") != "" || c.String("rm-pgp") != "" || c.String("rm-gcp-kms") != "" || c.String("rm-hc-vault-transit") != "" || c.String("rm-azure-kv") != "" || c.String("rm-age") != "" { return common.NewExitError("Error: cannot add or remove keys on non-existent files, use `--kms` and `--pgp` instead.", codes.CannotChangeKeysFromNonExistentFile) } if c.Bool("encrypt") || c.Bool("decrypt") || c.Bool("rotate") { @@ -802,6 +832,13 @@ func main() { for _, k := range hcVaultKeys { addMasterKeys = append(addMasterKeys, k) } + ageKeys, err := age.MasterKeysFromRecipients(c.String("add-age")) + if err != nil { + return err + } + for _, k := range ageKeys { + addMasterKeys = append(addMasterKeys, k) + } var rmMasterKeys []keys.MasterKey for _, k := range kms.MasterKeysFromArnString(c.String("rm-kms"), kmsEncryptionContext, c.String("aws-profile")) { @@ -827,6 +864,13 @@ func main() { for _, k := range hcVaultKeys { rmMasterKeys = append(rmMasterKeys, k) } + ageKeys, err = age.MasterKeysFromRecipients(c.String("rm-age")) + if err != nil { + return err + } + for _, k := range ageKeys { + rmMasterKeys = append(rmMasterKeys, k) + } output, err = rotate(rotateOpts{ OutputStore: outputStore, @@ -1023,6 +1067,7 @@ func keyGroups(c *cli.Context, file string) ([]sops.KeyGroup, error) { var cloudKmsKeys []keys.MasterKey var azkvKeys []keys.MasterKey var hcVaultMkKeys []keys.MasterKey + var ageMasterKeys []keys.MasterKey kmsEncryptionContext := kms.ParseKMSContext(c.String("encryption-context")) if c.String("encryption-context") != "" && kmsEncryptionContext == nil { return nil, common.NewExitError("Invalid KMS encryption context format", codes.ErrorInvalidKMSEncryptionContextFormat) @@ -1060,7 +1105,16 @@ func keyGroups(c *cli.Context, file string) ([]sops.KeyGroup, error) { pgpKeys = append(pgpKeys, k) } } - if c.String("kms") == "" && c.String("pgp") == "" && c.String("gcp-kms") == "" && c.String("azure-kv") == "" && c.String("hc-vault-transit") == "" { + if c.String("age") != "" { + ageKeys, err := age.MasterKeysFromRecipients(c.String("age")) + if err != nil { + return nil, err + } + for _, k := range ageKeys { + ageMasterKeys = append(ageMasterKeys, k) + } + } + if c.String("kms") == "" && c.String("pgp") == "" && c.String("gcp-kms") == "" && c.String("azure-kv") == "" && c.String("hc-vault-transit") == "" && c.String("age") == "" { conf, err := loadConfig(c, file, kmsEncryptionContext) // config file might just not be supplied, without any error if conf == nil { @@ -1078,6 +1132,7 @@ func keyGroups(c *cli.Context, file string) ([]sops.KeyGroup, error) { group = append(group, azkvKeys...) group = append(group, pgpKeys...) group = append(group, hcVaultMkKeys...) + group = append(group, ageMasterKeys...) log.Debugf("Master keys available: %+v", group) return []sops.KeyGroup{group}, nil } diff --git a/go.mod b/go.mod index 323fdc46a..6b95c902f 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.13 require ( cloud.google.com/go v0.43.0 + filippo.io/age v1.0.0-beta4 github.com/Azure/azure-sdk-for-go v31.2.0+incompatible github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Azure/go-autorest/autorest v0.9.0 @@ -19,8 +20,8 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/fatih/color v1.7.0 - github.com/golang/protobuf v1.3.2 - github.com/google/go-cmp v0.3.0 + github.com/golang/protobuf v1.4.1 + github.com/google/go-cmp v0.5.0 github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect github.com/goware/prefixer v0.0.0-20160118172347-395022866408 @@ -40,11 +41,12 @@ require ( github.com/stretchr/testify v1.5.1 github.com/vektra/mockery v1.1.2 // indirect go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a - golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 + golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 google.golang.org/api v0.7.0 - google.golang.org/grpc v1.22.1 + google.golang.org/grpc v1.27.0 + google.golang.org/protobuf v1.25.0 gopkg.in/ini.v1 v1.44.0 gopkg.in/urfave/cli.v1 v1.20.0 gotest.tools v2.2.0+incompatible // indirect diff --git a/go.sum b/go.sum index aa870f0a9..393a3a15b 100644 --- a/go.sum +++ b/go.sum @@ -5,6 +5,8 @@ cloud.google.com/go v0.43.0 h1:banaiRPAM8kUVYneOSkhgcDsLzEvL25FinuiSZaH/2w= cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= +filippo.io/age v1.0.0-beta4 h1:czSjaSa0owsI5gw/cE9yI/mfTiuhgYjozHI96v0PVJo= +filippo.io/age v1.0.0-beta4/go.mod h1:TOa3exZvzRCLfjmbJGsqwSQ0HtWjJfTTCQnQsNCC4E0= github.com/Azure/azure-sdk-for-go v31.2.0+incompatible h1:kZFnTLmdQYNGfakatSivKHUfUnDZhqNdchHD4oIhp5k= github.com/Azure/azure-sdk-for-go v31.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= @@ -60,6 +62,7 @@ github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEe github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc h1:TP+534wVlf61smEIq1nwLLAjQVEK2EADoW3CX9AuT+8= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -77,6 +80,8 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= @@ -99,6 +104,13 @@ github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -107,6 +119,10 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -224,6 +240,7 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -233,6 +250,8 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= @@ -247,6 +266,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/vektra/mockery v1.1.2 h1:uc0Yn67rJpjt8U/mAZimdCKn9AeA97BOkjpmtBSlfP4= @@ -267,6 +287,8 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49N golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -370,6 +392,9 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610 h1:Ygq9/SRJX9+dU0WCIICM8RkWvDw03lvB77hrhJnpxfU= google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -377,14 +402,26 @@ google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.22.1 h1:/7cs52RnTJmD43s3uxzlq2U7nqVTd/37viQwMrMNlOM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0= gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -398,6 +435,7 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/keyservice/keyservice.go b/keyservice/keyservice.go index f60e15822..103e3e6dc 100644 --- a/keyservice/keyservice.go +++ b/keyservice/keyservice.go @@ -7,6 +7,7 @@ package keyservice import ( "fmt" + "go.mozilla.org/sops/v3/age" "go.mozilla.org/sops/v3/azkv" "go.mozilla.org/sops/v3/gcpkms" "go.mozilla.org/sops/v3/hcvault" @@ -69,6 +70,14 @@ func KeyFromMasterKey(mk keys.MasterKey) Key { }, }, } + case *age.MasterKey: + return Key{ + KeyType: &Key_AgeKey{ + AgeKey: &AgeKey{ + Recipient: mk.Recipient, + }, + }, + } default: panic(fmt.Sprintf("Tried to convert unknown MasterKey type %T to keyservice.Key", mk)) } diff --git a/keyservice/keyservice.pb.go b/keyservice/keyservice.pb.go index c8177144b..ead3ccfd1 100644 --- a/keyservice/keyservice.pb.go +++ b/keyservice/keyservice.pb.go @@ -1,67 +1,129 @@ // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.23.0 +// protoc v3.13.0 // source: keyservice/keyservice.proto package keyservice import ( context "context" - fmt "fmt" - math "math" - proto "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 type Key struct { - // Types that are valid to be assigned to KeyType: + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to KeyType: // *Key_KmsKey // *Key_PgpKey // *Key_GcpKmsKey // *Key_AzureKeyvaultKey // *Key_VaultKey - KeyType isKey_KeyType `protobuf_oneof:"key_type"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + // *Key_AgeKey + KeyType isKey_KeyType `protobuf_oneof:"key_type"` +} + +func (x *Key) Reset() { + *x = Key{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Key) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Key) ProtoMessage() {} + +func (x *Key) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *Key) Reset() { *m = Key{} } -func (m *Key) String() string { return proto.CompactTextString(m) } -func (*Key) ProtoMessage() {} +// Deprecated: Use Key.ProtoReflect.Descriptor instead. func (*Key) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{0} + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{0} } -func (m *Key) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_Key.Unmarshal(m, b) +func (m *Key) GetKeyType() isKey_KeyType { + if m != nil { + return m.KeyType + } + return nil } -func (m *Key) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_Key.Marshal(b, m, deterministic) + +func (x *Key) GetKmsKey() *KmsKey { + if x, ok := x.GetKeyType().(*Key_KmsKey); ok { + return x.KmsKey + } + return nil +} + +func (x *Key) GetPgpKey() *PgpKey { + if x, ok := x.GetKeyType().(*Key_PgpKey); ok { + return x.PgpKey + } + return nil } -func (m *Key) XXX_Merge(src proto.Message) { - xxx_messageInfo_Key.Merge(m, src) + +func (x *Key) GetGcpKmsKey() *GcpKmsKey { + if x, ok := x.GetKeyType().(*Key_GcpKmsKey); ok { + return x.GcpKmsKey + } + return nil } -func (m *Key) XXX_Size() int { - return xxx_messageInfo_Key.Size(m) + +func (x *Key) GetAzureKeyvaultKey() *AzureKeyVaultKey { + if x, ok := x.GetKeyType().(*Key_AzureKeyvaultKey); ok { + return x.AzureKeyvaultKey + } + return nil } -func (m *Key) XXX_DiscardUnknown() { - xxx_messageInfo_Key.DiscardUnknown(m) + +func (x *Key) GetVaultKey() *VaultKey { + if x, ok := x.GetKeyType().(*Key_VaultKey); ok { + return x.VaultKey + } + return nil } -var xxx_messageInfo_Key proto.InternalMessageInfo +func (x *Key) GetAgeKey() *AgeKey { + if x, ok := x.GetKeyType().(*Key_AgeKey); ok { + return x.AgeKey + } + return nil +} type isKey_KeyType interface { isKey_KeyType() @@ -87,6 +149,10 @@ type Key_VaultKey struct { VaultKey *VaultKey `protobuf:"bytes,5,opt,name=vault_key,json=vaultKey,proto3,oneof"` } +type Key_AgeKey struct { + AgeKey *AgeKey `protobuf:"bytes,6,opt,name=age_key,json=ageKey,proto3,oneof"` +} + func (*Key_KmsKey) isKey_KeyType() {} func (*Key_PgpKey) isKey_KeyType() {} @@ -97,545 +163,852 @@ func (*Key_AzureKeyvaultKey) isKey_KeyType() {} func (*Key_VaultKey) isKey_KeyType() {} -func (m *Key) GetKeyType() isKey_KeyType { - if m != nil { - return m.KeyType - } - return nil -} +func (*Key_AgeKey) isKey_KeyType() {} -func (m *Key) GetKmsKey() *KmsKey { - if x, ok := m.GetKeyType().(*Key_KmsKey); ok { - return x.KmsKey - } - return nil -} +type PgpKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *Key) GetPgpKey() *PgpKey { - if x, ok := m.GetKeyType().(*Key_PgpKey); ok { - return x.PgpKey - } - return nil + Fingerprint string `protobuf:"bytes,1,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` } -func (m *Key) GetGcpKmsKey() *GcpKmsKey { - if x, ok := m.GetKeyType().(*Key_GcpKmsKey); ok { - return x.GcpKmsKey +func (x *PgpKey) Reset() { + *x = PgpKey{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return nil } -func (m *Key) GetAzureKeyvaultKey() *AzureKeyVaultKey { - if x, ok := m.GetKeyType().(*Key_AzureKeyvaultKey); ok { - return x.AzureKeyvaultKey - } - return nil +func (x *PgpKey) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *Key) GetVaultKey() *VaultKey { - if x, ok := m.GetKeyType().(*Key_VaultKey); ok { - return x.VaultKey - } - return nil -} +func (*PgpKey) ProtoMessage() {} -// XXX_OneofWrappers is for the internal use of the proto package. -func (*Key) XXX_OneofWrappers() []interface{} { - return []interface{}{ - (*Key_KmsKey)(nil), - (*Key_PgpKey)(nil), - (*Key_GcpKmsKey)(nil), - (*Key_AzureKeyvaultKey)(nil), - (*Key_VaultKey)(nil), +func (x *PgpKey) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } + return mi.MessageOf(x) } -type PgpKey struct { - Fingerprint string `protobuf:"bytes,1,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *PgpKey) Reset() { *m = PgpKey{} } -func (m *PgpKey) String() string { return proto.CompactTextString(m) } -func (*PgpKey) ProtoMessage() {} +// Deprecated: Use PgpKey.ProtoReflect.Descriptor instead. func (*PgpKey) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{1} + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{1} } -func (m *PgpKey) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_PgpKey.Unmarshal(m, b) -} -func (m *PgpKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_PgpKey.Marshal(b, m, deterministic) -} -func (m *PgpKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_PgpKey.Merge(m, src) -} -func (m *PgpKey) XXX_Size() int { - return xxx_messageInfo_PgpKey.Size(m) -} -func (m *PgpKey) XXX_DiscardUnknown() { - xxx_messageInfo_PgpKey.DiscardUnknown(m) -} - -var xxx_messageInfo_PgpKey proto.InternalMessageInfo - -func (m *PgpKey) GetFingerprint() string { - if m != nil { - return m.Fingerprint +func (x *PgpKey) GetFingerprint() string { + if x != nil { + return x.Fingerprint } return "" } type KmsKey struct { - Arn string `protobuf:"bytes,1,opt,name=arn,proto3" json:"arn,omitempty"` - Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` - Context map[string]string `protobuf:"bytes,3,rep,name=context,proto3" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - AwsProfile string `protobuf:"bytes,4,opt,name=aws_profile,json=awsProfile,proto3" json:"aws_profile,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *KmsKey) Reset() { *m = KmsKey{} } -func (m *KmsKey) String() string { return proto.CompactTextString(m) } -func (*KmsKey) ProtoMessage() {} -func (*KmsKey) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{2} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Arn string `protobuf:"bytes,1,opt,name=arn,proto3" json:"arn,omitempty"` + Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"` + Context map[string]string `protobuf:"bytes,3,rep,name=context,proto3" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + AwsProfile string `protobuf:"bytes,4,opt,name=aws_profile,json=awsProfile,proto3" json:"aws_profile,omitempty"` +} + +func (x *KmsKey) Reset() { + *x = KmsKey{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *KmsKey) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_KmsKey.Unmarshal(m, b) -} -func (m *KmsKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_KmsKey.Marshal(b, m, deterministic) -} -func (m *KmsKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_KmsKey.Merge(m, src) +func (x *KmsKey) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *KmsKey) XXX_Size() int { - return xxx_messageInfo_KmsKey.Size(m) -} -func (m *KmsKey) XXX_DiscardUnknown() { - xxx_messageInfo_KmsKey.DiscardUnknown(m) + +func (*KmsKey) ProtoMessage() {} + +func (x *KmsKey) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_KmsKey proto.InternalMessageInfo +// Deprecated: Use KmsKey.ProtoReflect.Descriptor instead. +func (*KmsKey) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{2} +} -func (m *KmsKey) GetArn() string { - if m != nil { - return m.Arn +func (x *KmsKey) GetArn() string { + if x != nil { + return x.Arn } return "" } -func (m *KmsKey) GetRole() string { - if m != nil { - return m.Role +func (x *KmsKey) GetRole() string { + if x != nil { + return x.Role } return "" } -func (m *KmsKey) GetContext() map[string]string { - if m != nil { - return m.Context +func (x *KmsKey) GetContext() map[string]string { + if x != nil { + return x.Context } return nil } -func (m *KmsKey) GetAwsProfile() string { - if m != nil { - return m.AwsProfile +func (x *KmsKey) GetAwsProfile() string { + if x != nil { + return x.AwsProfile } return "" } type GcpKmsKey struct { - ResourceId string `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *GcpKmsKey) Reset() { *m = GcpKmsKey{} } -func (m *GcpKmsKey) String() string { return proto.CompactTextString(m) } -func (*GcpKmsKey) ProtoMessage() {} -func (*GcpKmsKey) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{3} + ResourceId string `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` } -func (m *GcpKmsKey) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_GcpKmsKey.Unmarshal(m, b) -} -func (m *GcpKmsKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_GcpKmsKey.Marshal(b, m, deterministic) -} -func (m *GcpKmsKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_GcpKmsKey.Merge(m, src) +func (x *GcpKmsKey) Reset() { + *x = GcpKmsKey{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *GcpKmsKey) XXX_Size() int { - return xxx_messageInfo_GcpKmsKey.Size(m) + +func (x *GcpKmsKey) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *GcpKmsKey) XXX_DiscardUnknown() { - xxx_messageInfo_GcpKmsKey.DiscardUnknown(m) + +func (*GcpKmsKey) ProtoMessage() {} + +func (x *GcpKmsKey) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_GcpKmsKey proto.InternalMessageInfo +// Deprecated: Use GcpKmsKey.ProtoReflect.Descriptor instead. +func (*GcpKmsKey) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{3} +} -func (m *GcpKmsKey) GetResourceId() string { - if m != nil { - return m.ResourceId +func (x *GcpKmsKey) GetResourceId() string { + if x != nil { + return x.ResourceId } return "" } type VaultKey struct { - VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` - EnginePath string `protobuf:"bytes,2,opt,name=engine_path,json=enginePath,proto3" json:"engine_path,omitempty"` - KeyName string `protobuf:"bytes,3,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *VaultKey) Reset() { *m = VaultKey{} } -func (m *VaultKey) String() string { return proto.CompactTextString(m) } -func (*VaultKey) ProtoMessage() {} -func (*VaultKey) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{4} + VaultAddress string `protobuf:"bytes,1,opt,name=vault_address,json=vaultAddress,proto3" json:"vault_address,omitempty"` + EnginePath string `protobuf:"bytes,2,opt,name=engine_path,json=enginePath,proto3" json:"engine_path,omitempty"` + KeyName string `protobuf:"bytes,3,opt,name=key_name,json=keyName,proto3" json:"key_name,omitempty"` } -func (m *VaultKey) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_VaultKey.Unmarshal(m, b) -} -func (m *VaultKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_VaultKey.Marshal(b, m, deterministic) -} -func (m *VaultKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_VaultKey.Merge(m, src) +func (x *VaultKey) Reset() { + *x = VaultKey{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *VaultKey) XXX_Size() int { - return xxx_messageInfo_VaultKey.Size(m) + +func (x *VaultKey) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *VaultKey) XXX_DiscardUnknown() { - xxx_messageInfo_VaultKey.DiscardUnknown(m) + +func (*VaultKey) ProtoMessage() {} + +func (x *VaultKey) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_VaultKey proto.InternalMessageInfo +// Deprecated: Use VaultKey.ProtoReflect.Descriptor instead. +func (*VaultKey) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{4} +} -func (m *VaultKey) GetVaultAddress() string { - if m != nil { - return m.VaultAddress +func (x *VaultKey) GetVaultAddress() string { + if x != nil { + return x.VaultAddress } return "" } -func (m *VaultKey) GetEnginePath() string { - if m != nil { - return m.EnginePath +func (x *VaultKey) GetEnginePath() string { + if x != nil { + return x.EnginePath } return "" } -func (m *VaultKey) GetKeyName() string { - if m != nil { - return m.KeyName +func (x *VaultKey) GetKeyName() string { + if x != nil { + return x.KeyName } return "" } type AzureKeyVaultKey struct { - VaultUrl string `protobuf:"bytes,1,opt,name=vault_url,json=vaultUrl,proto3" json:"vault_url,omitempty"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *AzureKeyVaultKey) Reset() { *m = AzureKeyVaultKey{} } -func (m *AzureKeyVaultKey) String() string { return proto.CompactTextString(m) } -func (*AzureKeyVaultKey) ProtoMessage() {} -func (*AzureKeyVaultKey) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{5} + VaultUrl string `protobuf:"bytes,1,opt,name=vault_url,json=vaultUrl,proto3" json:"vault_url,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` } -func (m *AzureKeyVaultKey) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_AzureKeyVaultKey.Unmarshal(m, b) -} -func (m *AzureKeyVaultKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_AzureKeyVaultKey.Marshal(b, m, deterministic) -} -func (m *AzureKeyVaultKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_AzureKeyVaultKey.Merge(m, src) +func (x *AzureKeyVaultKey) Reset() { + *x = AzureKeyVaultKey{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *AzureKeyVaultKey) XXX_Size() int { - return xxx_messageInfo_AzureKeyVaultKey.Size(m) + +func (x *AzureKeyVaultKey) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *AzureKeyVaultKey) XXX_DiscardUnknown() { - xxx_messageInfo_AzureKeyVaultKey.DiscardUnknown(m) + +func (*AzureKeyVaultKey) ProtoMessage() {} + +func (x *AzureKeyVaultKey) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_AzureKeyVaultKey proto.InternalMessageInfo +// Deprecated: Use AzureKeyVaultKey.ProtoReflect.Descriptor instead. +func (*AzureKeyVaultKey) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{5} +} -func (m *AzureKeyVaultKey) GetVaultUrl() string { - if m != nil { - return m.VaultUrl +func (x *AzureKeyVaultKey) GetVaultUrl() string { + if x != nil { + return x.VaultUrl } return "" } -func (m *AzureKeyVaultKey) GetName() string { - if m != nil { - return m.Name +func (x *AzureKeyVaultKey) GetName() string { + if x != nil { + return x.Name } return "" } -func (m *AzureKeyVaultKey) GetVersion() string { - if m != nil { - return m.Version +func (x *AzureKeyVaultKey) GetVersion() string { + if x != nil { + return x.Version } return "" } -type EncryptRequest struct { - Key *Key `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Plaintext []byte `protobuf:"bytes,2,opt,name=plaintext,proto3" json:"plaintext,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` +type AgeKey struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Recipient string `protobuf:"bytes,1,opt,name=recipient,proto3" json:"recipient,omitempty"` } -func (m *EncryptRequest) Reset() { *m = EncryptRequest{} } -func (m *EncryptRequest) String() string { return proto.CompactTextString(m) } -func (*EncryptRequest) ProtoMessage() {} -func (*EncryptRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{6} +func (x *AgeKey) Reset() { + *x = AgeKey{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AgeKey) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AgeKey) ProtoMessage() {} + +func (x *AgeKey) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *EncryptRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EncryptRequest.Unmarshal(m, b) +// Deprecated: Use AgeKey.ProtoReflect.Descriptor instead. +func (*AgeKey) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{6} } -func (m *EncryptRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EncryptRequest.Marshal(b, m, deterministic) + +func (x *AgeKey) GetRecipient() string { + if x != nil { + return x.Recipient + } + return "" } -func (m *EncryptRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_EncryptRequest.Merge(m, src) + +type EncryptRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Key *Key `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Plaintext []byte `protobuf:"bytes,2,opt,name=plaintext,proto3" json:"plaintext,omitempty"` } -func (m *EncryptRequest) XXX_Size() int { - return xxx_messageInfo_EncryptRequest.Size(m) + +func (x *EncryptRequest) Reset() { + *x = EncryptRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *EncryptRequest) XXX_DiscardUnknown() { - xxx_messageInfo_EncryptRequest.DiscardUnknown(m) + +func (x *EncryptRequest) String() string { + return protoimpl.X.MessageStringOf(x) } -var xxx_messageInfo_EncryptRequest proto.InternalMessageInfo +func (*EncryptRequest) ProtoMessage() {} -func (m *EncryptRequest) GetKey() *Key { - if m != nil { - return m.Key +func (x *EncryptRequest) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EncryptRequest.ProtoReflect.Descriptor instead. +func (*EncryptRequest) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{7} +} + +func (x *EncryptRequest) GetKey() *Key { + if x != nil { + return x.Key } return nil } -func (m *EncryptRequest) GetPlaintext() []byte { - if m != nil { - return m.Plaintext +func (x *EncryptRequest) GetPlaintext() []byte { + if x != nil { + return x.Plaintext } return nil } type EncryptResponse struct { - Ciphertext []byte `protobuf:"bytes,1,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *EncryptResponse) Reset() { *m = EncryptResponse{} } -func (m *EncryptResponse) String() string { return proto.CompactTextString(m) } -func (*EncryptResponse) ProtoMessage() {} -func (*EncryptResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{7} + Ciphertext []byte `protobuf:"bytes,1,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` } -func (m *EncryptResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_EncryptResponse.Unmarshal(m, b) -} -func (m *EncryptResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_EncryptResponse.Marshal(b, m, deterministic) -} -func (m *EncryptResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_EncryptResponse.Merge(m, src) +func (x *EncryptResponse) Reset() { + *x = EncryptResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *EncryptResponse) XXX_Size() int { - return xxx_messageInfo_EncryptResponse.Size(m) + +func (x *EncryptResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *EncryptResponse) XXX_DiscardUnknown() { - xxx_messageInfo_EncryptResponse.DiscardUnknown(m) + +func (*EncryptResponse) ProtoMessage() {} + +func (x *EncryptResponse) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_EncryptResponse proto.InternalMessageInfo +// Deprecated: Use EncryptResponse.ProtoReflect.Descriptor instead. +func (*EncryptResponse) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{8} +} -func (m *EncryptResponse) GetCiphertext() []byte { - if m != nil { - return m.Ciphertext +func (x *EncryptResponse) GetCiphertext() []byte { + if x != nil { + return x.Ciphertext } return nil } type DecryptRequest struct { - Key *Key `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Ciphertext []byte `protobuf:"bytes,2,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *DecryptRequest) Reset() { *m = DecryptRequest{} } -func (m *DecryptRequest) String() string { return proto.CompactTextString(m) } -func (*DecryptRequest) ProtoMessage() {} -func (*DecryptRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{8} + Key *Key `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Ciphertext []byte `protobuf:"bytes,2,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` } -func (m *DecryptRequest) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DecryptRequest.Unmarshal(m, b) -} -func (m *DecryptRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DecryptRequest.Marshal(b, m, deterministic) -} -func (m *DecryptRequest) XXX_Merge(src proto.Message) { - xxx_messageInfo_DecryptRequest.Merge(m, src) +func (x *DecryptRequest) Reset() { + *x = DecryptRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *DecryptRequest) XXX_Size() int { - return xxx_messageInfo_DecryptRequest.Size(m) + +func (x *DecryptRequest) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *DecryptRequest) XXX_DiscardUnknown() { - xxx_messageInfo_DecryptRequest.DiscardUnknown(m) + +func (*DecryptRequest) ProtoMessage() {} + +func (x *DecryptRequest) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_DecryptRequest proto.InternalMessageInfo +// Deprecated: Use DecryptRequest.ProtoReflect.Descriptor instead. +func (*DecryptRequest) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{9} +} -func (m *DecryptRequest) GetKey() *Key { - if m != nil { - return m.Key +func (x *DecryptRequest) GetKey() *Key { + if x != nil { + return x.Key } return nil } -func (m *DecryptRequest) GetCiphertext() []byte { - if m != nil { - return m.Ciphertext +func (x *DecryptRequest) GetCiphertext() []byte { + if x != nil { + return x.Ciphertext } return nil } type DecryptResponse struct { - Plaintext []byte `protobuf:"bytes,1,opt,name=plaintext,proto3" json:"plaintext,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields -func (m *DecryptResponse) Reset() { *m = DecryptResponse{} } -func (m *DecryptResponse) String() string { return proto.CompactTextString(m) } -func (*DecryptResponse) ProtoMessage() {} -func (*DecryptResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_8c1e2c407c293790, []int{9} + Plaintext []byte `protobuf:"bytes,1,opt,name=plaintext,proto3" json:"plaintext,omitempty"` } -func (m *DecryptResponse) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_DecryptResponse.Unmarshal(m, b) -} -func (m *DecryptResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_DecryptResponse.Marshal(b, m, deterministic) -} -func (m *DecryptResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_DecryptResponse.Merge(m, src) +func (x *DecryptResponse) Reset() { + *x = DecryptResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_keyservice_keyservice_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *DecryptResponse) XXX_Size() int { - return xxx_messageInfo_DecryptResponse.Size(m) + +func (x *DecryptResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *DecryptResponse) XXX_DiscardUnknown() { - xxx_messageInfo_DecryptResponse.DiscardUnknown(m) + +func (*DecryptResponse) ProtoMessage() {} + +func (x *DecryptResponse) ProtoReflect() protoreflect.Message { + mi := &file_keyservice_keyservice_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -var xxx_messageInfo_DecryptResponse proto.InternalMessageInfo +// Deprecated: Use DecryptResponse.ProtoReflect.Descriptor instead. +func (*DecryptResponse) Descriptor() ([]byte, []int) { + return file_keyservice_keyservice_proto_rawDescGZIP(), []int{10} +} -func (m *DecryptResponse) GetPlaintext() []byte { - if m != nil { - return m.Plaintext +func (x *DecryptResponse) GetPlaintext() []byte { + if x != nil { + return x.Plaintext } return nil } -func init() { - proto.RegisterType((*Key)(nil), "Key") - proto.RegisterType((*PgpKey)(nil), "PgpKey") - proto.RegisterType((*KmsKey)(nil), "KmsKey") - proto.RegisterMapType((map[string]string)(nil), "KmsKey.ContextEntry") - proto.RegisterType((*GcpKmsKey)(nil), "GcpKmsKey") - proto.RegisterType((*VaultKey)(nil), "VaultKey") - proto.RegisterType((*AzureKeyVaultKey)(nil), "AzureKeyVaultKey") - proto.RegisterType((*EncryptRequest)(nil), "EncryptRequest") - proto.RegisterType((*EncryptResponse)(nil), "EncryptResponse") - proto.RegisterType((*DecryptRequest)(nil), "DecryptRequest") - proto.RegisterType((*DecryptResponse)(nil), "DecryptResponse") -} - -func init() { proto.RegisterFile("keyservice/keyservice.proto", fileDescriptor_8c1e2c407c293790) } - -var fileDescriptor_8c1e2c407c293790 = []byte{ - // 574 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0x5d, 0x6f, 0xd3, 0x30, - 0x14, 0x5d, 0xd6, 0xad, 0x5d, 0x6e, 0xca, 0x5a, 0xac, 0x09, 0x8d, 0x0d, 0xc1, 0x30, 0x2f, 0x13, - 0x9a, 0x3c, 0x51, 0x5e, 0xd0, 0xde, 0x06, 0x0c, 0x86, 0x2a, 0xa1, 0x29, 0x08, 0xde, 0x50, 0xe5, - 0xa5, 0x77, 0x6d, 0x94, 0x34, 0x31, 0x76, 0xd2, 0x61, 0xfe, 0x1a, 0x7f, 0x8b, 0x1f, 0x80, 0xfc, - 0x91, 0x7e, 0xf1, 0xc2, 0xdb, 0xf5, 0xc9, 0x39, 0xe7, 0x5e, 0x9f, 0xeb, 0x16, 0x8e, 0x33, 0xd4, - 0x0a, 0xe5, 0x3c, 0x4d, 0xf0, 0x7c, 0x59, 0x32, 0x21, 0xcb, 0xaa, 0xa4, 0x7f, 0x02, 0x68, 0x0d, - 0x51, 0x13, 0x0a, 0x9d, 0x6c, 0xa6, 0x46, 0x19, 0xea, 0xc3, 0xe0, 0x24, 0x38, 0x8d, 0x06, 0x1d, - 0x36, 0x9c, 0xa9, 0x21, 0xea, 0xeb, 0xad, 0xb8, 0x9d, 0xd9, 0xca, 0x70, 0xc4, 0x44, 0x58, 0xce, - 0xb6, 0xe7, 0xdc, 0x4c, 0x84, 0xe7, 0x08, 0x5b, 0x91, 0x33, 0x88, 0x26, 0x89, 0x18, 0x35, 0x5e, - 0x2d, 0xcb, 0x03, 0xf6, 0x31, 0x11, 0x0b, 0xbb, 0x70, 0xd2, 0x1c, 0xc8, 0x25, 0x10, 0xfe, 0xab, - 0x96, 0x68, 0xb8, 0x73, 0x5e, 0xe7, 0x95, 0x15, 0xed, 0x58, 0xd1, 0x43, 0x76, 0x69, 0x3e, 0x0d, - 0x51, 0x7f, 0x33, 0x5f, 0x9c, 0xb6, 0xcf, 0x3d, 0x36, 0xf7, 0x18, 0x39, 0x85, 0x70, 0xa9, 0xdc, - 0xb5, 0xca, 0x90, 0xad, 0x28, 0xf6, 0x1a, 0xe6, 0x5b, 0x80, 0xbd, 0x0c, 0xf5, 0xa8, 0xd2, 0x02, - 0xe9, 0x4b, 0x68, 0xbb, 0xd1, 0xc9, 0x09, 0x44, 0x77, 0x69, 0x31, 0x41, 0x29, 0x64, 0x5a, 0x54, - 0xf6, 0xf2, 0x61, 0xbc, 0x0a, 0xd1, 0xdf, 0x01, 0xb4, 0xfd, 0xbc, 0x7d, 0x68, 0x71, 0x59, 0x78, - 0x92, 0x29, 0x09, 0x81, 0x1d, 0x59, 0xe6, 0x68, 0x03, 0x09, 0x63, 0x5b, 0x13, 0x06, 0x9d, 0xa4, - 0x2c, 0x2a, 0xfc, 0x59, 0x1d, 0xb6, 0x4e, 0x5a, 0xa7, 0xd1, 0xe0, 0xc0, 0x67, 0xc9, 0xde, 0x39, - 0xf8, 0xaa, 0xa8, 0xa4, 0x8e, 0x1b, 0x12, 0x79, 0x06, 0x11, 0xbf, 0x57, 0x23, 0x21, 0xcb, 0xbb, - 0x34, 0x47, 0x7b, 0xfd, 0x30, 0x06, 0x7e, 0xaf, 0x6e, 0x1c, 0x72, 0x74, 0x01, 0xdd, 0x55, 0xa5, - 0x19, 0xa3, 0x59, 0x54, 0x18, 0x9b, 0x92, 0x1c, 0xc0, 0xee, 0x9c, 0xe7, 0x75, 0x33, 0x87, 0x3b, - 0x5c, 0x6c, 0xbf, 0x09, 0xe8, 0x19, 0x84, 0x8b, 0xf0, 0x4d, 0x27, 0x89, 0xaa, 0xac, 0x65, 0x82, - 0xa3, 0x74, 0xec, 0x0d, 0xa0, 0x81, 0x3e, 0x8d, 0xe9, 0x0c, 0xf6, 0x9a, 0xec, 0xc8, 0x0b, 0x78, - 0xe0, 0x92, 0xe5, 0xe3, 0xb1, 0x44, 0xa5, 0x3c, 0xbd, 0x6b, 0xc1, 0x4b, 0x87, 0x91, 0xe7, 0xd0, - 0xbd, 0xe5, 0x49, 0x86, 0xc5, 0x78, 0x24, 0x78, 0x35, 0xf5, 0xfd, 0x23, 0x8f, 0xdd, 0xf0, 0x6a, - 0x4a, 0x1e, 0xbb, 0xdc, 0x0b, 0x3e, 0x43, 0xfb, 0x1e, 0xc2, 0xb8, 0x93, 0xa1, 0xfe, 0xcc, 0x67, - 0x48, 0xbf, 0x43, 0x7f, 0x73, 0xc9, 0xe4, 0xb8, 0x59, 0x68, 0x2d, 0x73, 0xdf, 0xd2, 0xed, 0xf0, - 0xab, 0xcc, 0x4d, 0xdc, 0xd6, 0xc7, 0xc7, 0x6d, 0x6a, 0x72, 0x08, 0x9d, 0x39, 0x4a, 0x95, 0x96, - 0x45, 0x63, 0xef, 0x8f, 0xf4, 0x03, 0xec, 0x5f, 0x15, 0x89, 0xd4, 0xa2, 0x8a, 0xf1, 0x47, 0x8d, - 0xaa, 0x22, 0x8f, 0x96, 0xc9, 0x45, 0x83, 0x1d, 0x36, 0x44, 0xed, 0xf2, 0x7b, 0x02, 0xa1, 0xc8, - 0x79, 0xea, 0x96, 0x66, 0xcc, 0xbb, 0xf1, 0x12, 0xa0, 0xaf, 0xa0, 0xb7, 0xf0, 0x51, 0xa2, 0x2c, - 0x14, 0x92, 0xa7, 0x00, 0x49, 0x2a, 0xa6, 0x28, 0xad, 0x22, 0xb0, 0x8a, 0x15, 0x84, 0x5e, 0xc3, - 0xfe, 0x7b, 0xfc, 0xaf, 0xd6, 0xeb, 0x4e, 0xdb, 0xff, 0x38, 0x9d, 0x43, 0x6f, 0xe1, 0xe4, 0x9b, - 0xaf, 0x4d, 0x1b, 0x6c, 0x4c, 0x3b, 0xc8, 0x01, 0x86, 0xa8, 0xbf, 0xb8, 0x9f, 0xb9, 0x79, 0x8c, - 0x7e, 0x76, 0xd2, 0x63, 0xeb, 0x69, 0x1c, 0xf5, 0xd9, 0xc6, 0xb5, 0xe8, 0x96, 0xe1, 0xfb, 0x76, - 0xa4, 0xc7, 0xd6, 0xaf, 0x70, 0xd4, 0x67, 0x1b, 0x93, 0xd0, 0xad, 0xdb, 0xb6, 0xfd, 0x1f, 0x79, - 0xfd, 0x37, 0x00, 0x00, 0xff, 0xff, 0x9b, 0x65, 0x80, 0xa7, 0x66, 0x04, 0x00, 0x00, +var File_keyservice_keyservice_proto protoreflect.FileDescriptor + +var file_keyservice_keyservice_proto_rawDesc = []byte{ + 0x0a, 0x1b, 0x6b, 0x65, 0x79, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x6b, 0x65, 0x79, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x98, 0x02, + 0x0a, 0x03, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x0a, 0x07, 0x6b, 0x6d, 0x73, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x48, + 0x00, 0x52, 0x06, 0x6b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x0a, 0x07, 0x70, 0x67, 0x70, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x50, 0x67, 0x70, + 0x4b, 0x65, 0x79, 0x48, 0x00, 0x52, 0x06, 0x70, 0x67, 0x70, 0x4b, 0x65, 0x79, 0x12, 0x2c, 0x0a, + 0x0b, 0x67, 0x63, 0x70, 0x5f, 0x6b, 0x6d, 0x73, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x47, 0x63, 0x70, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x48, 0x00, + 0x52, 0x09, 0x67, 0x63, 0x70, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x12, 0x41, 0x0a, 0x12, 0x61, + 0x7a, 0x75, 0x72, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6b, 0x65, + 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x4b, + 0x65, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x79, 0x48, 0x00, 0x52, 0x10, 0x61, 0x7a, + 0x75, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x28, + 0x0a, 0x09, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x09, 0x2e, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x79, 0x48, 0x00, 0x52, 0x08, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x22, 0x0a, 0x07, 0x61, 0x67, 0x65, 0x5f, + 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x41, 0x67, 0x65, 0x4b, + 0x65, 0x79, 0x48, 0x00, 0x52, 0x06, 0x61, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x42, 0x0a, 0x0a, 0x08, + 0x6b, 0x65, 0x79, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2a, 0x0a, 0x06, 0x50, 0x67, 0x70, 0x4b, + 0x65, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, + 0x72, 0x69, 0x6e, 0x74, 0x22, 0xbb, 0x01, 0x0a, 0x06, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x61, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x2e, + 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x77, 0x73, 0x5f, 0x70, 0x72, 0x6f, + 0x66, 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x77, 0x73, 0x50, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x1a, 0x3a, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x22, 0x2c, 0x0a, 0x09, 0x47, 0x63, 0x70, 0x4b, 0x6d, 0x73, 0x4b, 0x65, 0x79, 0x12, + 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, + 0x22, 0x6b, 0x0a, 0x08, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, 0x79, 0x12, 0x23, 0x0a, 0x0d, + 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x5d, 0x0a, + 0x10, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x75, 0x6c, 0x74, 0x4b, 0x65, + 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x26, 0x0a, 0x06, + 0x41, 0x67, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, 0x69, + 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x63, 0x69, 0x70, + 0x69, 0x65, 0x6e, 0x74, 0x22, 0x46, 0x0a, 0x0e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x04, 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1c, + 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x31, 0x0a, 0x0f, + 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x22, + 0x48, 0x0a, 0x0e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x16, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x04, + 0x2e, 0x4b, 0x65, 0x79, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, + 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, + 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x22, 0x2f, 0x0a, 0x0f, 0x44, 0x65, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, + 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x09, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x32, 0x6c, 0x0a, 0x0a, 0x4b, 0x65, + 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2e, 0x0a, 0x07, 0x45, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x12, 0x0f, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x07, 0x44, 0x65, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x12, 0x0f, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x44, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_keyservice_keyservice_proto_rawDescOnce sync.Once + file_keyservice_keyservice_proto_rawDescData = file_keyservice_keyservice_proto_rawDesc +) + +func file_keyservice_keyservice_proto_rawDescGZIP() []byte { + file_keyservice_keyservice_proto_rawDescOnce.Do(func() { + file_keyservice_keyservice_proto_rawDescData = protoimpl.X.CompressGZIP(file_keyservice_keyservice_proto_rawDescData) + }) + return file_keyservice_keyservice_proto_rawDescData +} + +var file_keyservice_keyservice_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_keyservice_keyservice_proto_goTypes = []interface{}{ + (*Key)(nil), // 0: Key + (*PgpKey)(nil), // 1: PgpKey + (*KmsKey)(nil), // 2: KmsKey + (*GcpKmsKey)(nil), // 3: GcpKmsKey + (*VaultKey)(nil), // 4: VaultKey + (*AzureKeyVaultKey)(nil), // 5: AzureKeyVaultKey + (*AgeKey)(nil), // 6: AgeKey + (*EncryptRequest)(nil), // 7: EncryptRequest + (*EncryptResponse)(nil), // 8: EncryptResponse + (*DecryptRequest)(nil), // 9: DecryptRequest + (*DecryptResponse)(nil), // 10: DecryptResponse + nil, // 11: KmsKey.ContextEntry +} +var file_keyservice_keyservice_proto_depIdxs = []int32{ + 2, // 0: Key.kms_key:type_name -> KmsKey + 1, // 1: Key.pgp_key:type_name -> PgpKey + 3, // 2: Key.gcp_kms_key:type_name -> GcpKmsKey + 5, // 3: Key.azure_keyvault_key:type_name -> AzureKeyVaultKey + 4, // 4: Key.vault_key:type_name -> VaultKey + 6, // 5: Key.age_key:type_name -> AgeKey + 11, // 6: KmsKey.context:type_name -> KmsKey.ContextEntry + 0, // 7: EncryptRequest.key:type_name -> Key + 0, // 8: DecryptRequest.key:type_name -> Key + 7, // 9: KeyService.Encrypt:input_type -> EncryptRequest + 9, // 10: KeyService.Decrypt:input_type -> DecryptRequest + 8, // 11: KeyService.Encrypt:output_type -> EncryptResponse + 10, // 12: KeyService.Decrypt:output_type -> DecryptResponse + 11, // [11:13] is the sub-list for method output_type + 9, // [9:11] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name +} + +func init() { file_keyservice_keyservice_proto_init() } +func file_keyservice_keyservice_proto_init() { + if File_keyservice_keyservice_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_keyservice_keyservice_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Key); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PgpKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*KmsKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GcpKmsKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VaultKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AzureKeyVaultKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AgeKey); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EncryptRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EncryptResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DecryptRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_keyservice_keyservice_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DecryptResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + file_keyservice_keyservice_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*Key_KmsKey)(nil), + (*Key_PgpKey)(nil), + (*Key_GcpKmsKey)(nil), + (*Key_AzureKeyvaultKey)(nil), + (*Key_VaultKey)(nil), + (*Key_AgeKey)(nil), + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_keyservice_keyservice_proto_rawDesc, + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_keyservice_keyservice_proto_goTypes, + DependencyIndexes: file_keyservice_keyservice_proto_depIdxs, + MessageInfos: file_keyservice_keyservice_proto_msgTypes, + }.Build() + File_keyservice_keyservice_proto = out.File + file_keyservice_keyservice_proto_rawDesc = nil + file_keyservice_keyservice_proto_goTypes = nil + file_keyservice_keyservice_proto_depIdxs = nil } // Reference imports to suppress errors if they are not otherwise used. var _ context.Context -var _ grpc.ClientConn +var _ grpc.ClientConnInterface // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 +const _ = grpc.SupportPackageIsVersion6 // KeyServiceClient is the client API for KeyService service. // @@ -646,10 +1019,10 @@ type KeyServiceClient interface { } type keyServiceClient struct { - cc *grpc.ClientConn + cc grpc.ClientConnInterface } -func NewKeyServiceClient(cc *grpc.ClientConn) KeyServiceClient { +func NewKeyServiceClient(cc grpc.ClientConnInterface) KeyServiceClient { return &keyServiceClient{cc} } @@ -681,10 +1054,10 @@ type KeyServiceServer interface { type UnimplementedKeyServiceServer struct { } -func (*UnimplementedKeyServiceServer) Encrypt(ctx context.Context, req *EncryptRequest) (*EncryptResponse, error) { +func (*UnimplementedKeyServiceServer) Encrypt(context.Context, *EncryptRequest) (*EncryptResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Encrypt not implemented") } -func (*UnimplementedKeyServiceServer) Decrypt(ctx context.Context, req *DecryptRequest) (*DecryptResponse, error) { +func (*UnimplementedKeyServiceServer) Decrypt(context.Context, *DecryptRequest) (*DecryptResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Decrypt not implemented") } diff --git a/keyservice/keyservice.proto b/keyservice/keyservice.proto index a6f5e436f..f2b7faa90 100644 --- a/keyservice/keyservice.proto +++ b/keyservice/keyservice.proto @@ -7,6 +7,7 @@ message Key { GcpKmsKey gcp_kms_key = 3; AzureKeyVaultKey azure_keyvault_key = 4; VaultKey vault_key = 5; + AgeKey age_key = 6; } } @@ -37,6 +38,10 @@ message AzureKeyVaultKey { string version = 3; } +message AgeKey { + string recipient = 1; +} + message EncryptRequest { Key key = 1; bytes plaintext = 2; diff --git a/keyservice/server.go b/keyservice/server.go index d2734bd97..aed4c9cde 100644 --- a/keyservice/server.go +++ b/keyservice/server.go @@ -3,6 +3,7 @@ package keyservice import ( "fmt" + "go.mozilla.org/sops/v3/age" "go.mozilla.org/sops/v3/azkv" "go.mozilla.org/sops/v3/gcpkms" "go.mozilla.org/sops/v3/hcvault" @@ -75,6 +76,20 @@ func (ks *Server) encryptWithVault(key *VaultKey, plaintext []byte) ([]byte, err return []byte(vaultKey.EncryptedKey), nil } +func (ks *Server) encryptWithAge(key *AgeKey, plaintext []byte) ([]byte, error) { + ageKey := age.MasterKey{ + Recipient: key.Recipient, + } + + err := ageKey.Encrypt(plaintext) + + if err != nil { + return nil, err + } + + return []byte(ageKey.EncryptedKey), nil +} + func (ks *Server) decryptWithPgp(key *PgpKey, ciphertext []byte) ([]byte, error) { pgpKey := pgp.NewMasterKeyFromFingerprint(key.Fingerprint) pgpKey.EncryptedKey = string(ciphertext) @@ -120,6 +135,15 @@ func (ks *Server) decryptWithVault(key *VaultKey, ciphertext []byte) ([]byte, er return []byte(plaintext), err } +func (ks *Server) decryptWithAge(key *AgeKey, ciphertext []byte) ([]byte, error) { + ageKey := age.MasterKey{ + Recipient: key.Recipient, + } + ageKey.EncryptedKey = string(ciphertext) + plaintext, err := ageKey.Decrypt() + return []byte(plaintext), err +} + // Encrypt takes an encrypt request and encrypts the provided plaintext with the provided key, returning the encrypted // result func (ks Server) Encrypt(ctx context.Context, @@ -167,6 +191,14 @@ func (ks Server) Encrypt(ctx context.Context, response = &EncryptResponse{ Ciphertext: ciphertext, } + case *Key_AgeKey: + ciphertext, err := ks.encryptWithAge(k.AgeKey, req.Plaintext) + if err != nil { + return nil, err + } + response = &EncryptResponse{ + Ciphertext: ciphertext, + } case nil: return nil, status.Errorf(codes.NotFound, "Must provide a key") default: @@ -261,6 +293,14 @@ func (ks Server) Decrypt(ctx context.Context, response = &DecryptResponse{ Plaintext: plaintext, } + case *Key_AgeKey: + plaintext, err := ks.decryptWithAge(k.AgeKey, req.Ciphertext) + if err != nil { + return nil, err + } + response = &DecryptResponse{ + Plaintext: plaintext, + } case nil: return nil, grpc.Errorf(codes.NotFound, "Must provide a key") default: diff --git a/stores/stores.go b/stores/stores.go index 236940fb2..da8781ab2 100644 --- a/stores/stores.go +++ b/stores/stores.go @@ -15,6 +15,7 @@ import ( "fmt" "go.mozilla.org/sops/v3" + "go.mozilla.org/sops/v3/age" "go.mozilla.org/sops/v3/azkv" "go.mozilla.org/sops/v3/gcpkms" "go.mozilla.org/sops/v3/hcvault" @@ -42,6 +43,7 @@ type Metadata struct { GCPKMSKeys []gcpkmskey `yaml:"gcp_kms" json:"gcp_kms"` AzureKeyVaultKeys []azkvkey `yaml:"azure_kv" json:"azure_kv"` VaultKeys []vaultkey `yaml:"hc_vault" json:"hc_vault"` + AgeKeys []agekey `yaml:"age" json:"age"` LastModified string `yaml:"lastmodified" json:"lastmodified"` MessageAuthenticationCode string `yaml:"mac" json:"mac"` PGPKeys []pgpkey `yaml:"pgp" json:"pgp"` @@ -58,6 +60,7 @@ type keygroup struct { GCPKMSKeys []gcpkmskey `yaml:"gcp_kms,omitempty" json:"gcp_kms,omitempty"` AzureKeyVaultKeys []azkvkey `yaml:"azure_kv,omitempty" json:"azure_kv,omitempty"` VaultKeys []vaultkey `yaml:"hc_vault" json:"hc_vault"` + AgeKeys []agekey `yaml:"age" json:"age"` } type pgpkey struct { @@ -97,6 +100,11 @@ type azkvkey struct { EncryptedDataKey string `yaml:"enc" json:"enc"` } +type agekey struct { + Recipient string `yaml:"recipient" json:"recipient"` + EncryptedDataKey string `yaml:"enc" json:"enc"` +} + // MetadataFromInternal converts an internal SOPS metadata representation to a representation appropriate for storage func MetadataFromInternal(sopsMetadata sops.Metadata) Metadata { var m Metadata @@ -115,6 +123,7 @@ func MetadataFromInternal(sopsMetadata sops.Metadata) Metadata { m.GCPKMSKeys = gcpkmsKeysFromGroup(group) m.VaultKeys = vaultKeysFromGroup(group) m.AzureKeyVaultKeys = azkvKeysFromGroup(group) + m.AgeKeys = ageKeysFromGroup(group) } else { for _, group := range sopsMetadata.KeyGroups { m.KeyGroups = append(m.KeyGroups, keygroup{ @@ -123,6 +132,7 @@ func MetadataFromInternal(sopsMetadata sops.Metadata) Metadata { GCPKMSKeys: gcpkmsKeysFromGroup(group), VaultKeys: vaultKeysFromGroup(group), AzureKeyVaultKeys: azkvKeysFromGroup(group), + AgeKeys: ageKeysFromGroup(group), }) } } @@ -206,6 +216,19 @@ func azkvKeysFromGroup(group sops.KeyGroup) (keys []azkvkey) { return } +func ageKeysFromGroup(group sops.KeyGroup) (keys []agekey) { + for _, key := range group { + switch key := key.(type) { + case *age.MasterKey: + keys = append(keys, agekey{ + Recipient: key.Recipient, + EncryptedDataKey: key.EncryptedKey, + }) + } + } + return +} + // ToInternal converts a storage-appropriate Metadata struct to a SOPS internal representation func (m *Metadata) ToInternal() (sops.Metadata, error) { lastModified, err := time.Parse(time.RFC3339, m.LastModified) @@ -251,7 +274,7 @@ func (m *Metadata) ToInternal() (sops.Metadata, error) { }, nil } -func internalGroupFrom(kmsKeys []kmskey, pgpKeys []pgpkey, gcpKmsKeys []gcpkmskey, azkvKeys []azkvkey, vaultKeys []vaultkey) (sops.KeyGroup, error) { +func internalGroupFrom(kmsKeys []kmskey, pgpKeys []pgpkey, gcpKmsKeys []gcpkmskey, azkvKeys []azkvkey, vaultKeys []vaultkey, ageKeys []agekey) (sops.KeyGroup, error) { var internalGroup sops.KeyGroup for _, kmsKey := range kmsKeys { k, err := kmsKey.toInternal() @@ -288,13 +311,20 @@ func internalGroupFrom(kmsKeys []kmskey, pgpKeys []pgpkey, gcpKmsKeys []gcpkmske } internalGroup = append(internalGroup, k) } + for _, ageKey := range ageKeys { + k, err := ageKey.toInternal() + if err != nil { + return nil, err + } + internalGroup = append(internalGroup, k) + } return internalGroup, nil } func (m *Metadata) internalKeygroups() ([]sops.KeyGroup, error) { var internalGroups []sops.KeyGroup - if len(m.PGPKeys) > 0 || len(m.KMSKeys) > 0 || len(m.GCPKMSKeys) > 0 || len(m.AzureKeyVaultKeys) > 0 || len(m.VaultKeys) > 0 { - internalGroup, err := internalGroupFrom(m.KMSKeys, m.PGPKeys, m.GCPKMSKeys, m.AzureKeyVaultKeys, m.VaultKeys) + if len(m.PGPKeys) > 0 || len(m.KMSKeys) > 0 || len(m.GCPKMSKeys) > 0 || len(m.AzureKeyVaultKeys) > 0 || len(m.VaultKeys) > 0 || len(m.AgeKeys) > 0 { + internalGroup, err := internalGroupFrom(m.KMSKeys, m.PGPKeys, m.GCPKMSKeys, m.AzureKeyVaultKeys, m.VaultKeys, m.AgeKeys) if err != nil { return nil, err } @@ -302,7 +332,7 @@ func (m *Metadata) internalKeygroups() ([]sops.KeyGroup, error) { return internalGroups, nil } else if len(m.KeyGroups) > 0 { for _, group := range m.KeyGroups { - internalGroup, err := internalGroupFrom(group.KMSKeys, group.PGPKeys, group.GCPKMSKeys, group.AzureKeyVaultKeys, group.VaultKeys) + internalGroup, err := internalGroupFrom(group.KMSKeys, group.PGPKeys, group.GCPKMSKeys, group.AzureKeyVaultKeys, group.VaultKeys, group.AgeKeys) if err != nil { return nil, err } @@ -381,6 +411,13 @@ func (pgpKey *pgpkey) toInternal() (*pgp.MasterKey, error) { }, nil } +func (ageKey *agekey) toInternal() (*age.MasterKey, error) { + return &age.MasterKey{ + EncryptedKey: ageKey.EncryptedDataKey, + Recipient: ageKey.Recipient, + }, nil +} + // ExampleComplexTree is an example sops.Tree object exhibiting complex relationships var ExampleComplexTree = sops.Tree{ Branches: sops.TreeBranches{ From 9ca46d0d96b16378f72c0c5107837ea3b32456ee Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Fri, 10 Jul 2020 22:39:43 -0700 Subject: [PATCH 03/40] Use idiomatic style for assignment and error handling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jörg Thalheim --- keyservice/server.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/keyservice/server.go b/keyservice/server.go index aed4c9cde..08249ff24 100644 --- a/keyservice/server.go +++ b/keyservice/server.go @@ -81,9 +81,7 @@ func (ks *Server) encryptWithAge(key *AgeKey, plaintext []byte) ([]byte, error) Recipient: key.Recipient, } - err := ageKey.Encrypt(plaintext) - - if err != nil { + if err := ageKey.Encrypt(plaintext); err != nil { return nil, err } From 9e4cbc93cf9fa8607c411e994aa65de9cf64aa67 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sat, 18 Jul 2020 04:00:25 -0700 Subject: [PATCH 04/40] Allow age key dir to be set with SOPS_AGE_KEY_DIR and add tests. --- ...lcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw.key | 3 ++ age/keysource.go | 15 ++++++++- age/keysource_test.go | 31 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 age/age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw.key create mode 100644 age/keysource_test.go diff --git a/age/age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw.key b/age/age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw.key new file mode 100644 index 000000000..c56eb4fab --- /dev/null +++ b/age/age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw.key @@ -0,0 +1,3 @@ +# created: 2020-07-18T03:16:47-07:00 +# public key: age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw +AGE-SECRET-KEY-1NJT5YCS2LWU4V4QAJQ6R4JNU7LXPDX602DZ9NUFANVU5GDTGUWCQ5T59M6 diff --git a/age/keysource.go b/age/keysource.go index 063b7225c..d819d2eb6 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "os" + "path/filepath" "strings" "filippo.io/age" @@ -75,7 +76,19 @@ func (key *MasterKey) SetEncryptedDataKey(enc []byte) { // Decrypt decrypts the EncryptedKey field with the age identity and returns the result. func (key *MasterKey) Decrypt() ([]byte, error) { - path := fmt.Sprintf("%s/.sops/age/%s.key", os.Getenv("HOME"), key.Recipient) + ageKeyDir, ok := os.LookupEnv("SOPS_AGE_KEY_DIR") + + if !ok { + userHomeDir, err := os.UserHomeDir() + + if err != nil { + return nil, fmt.Errorf("home directory could not be determined: %v", err) + } + + ageKeyDir = filepath.Join(userHomeDir, ".sops", "age") + } + + path := filepath.Join(ageKeyDir, fmt.Sprintf("%s.key", key.Recipient)) _, err := os.Stat(path) diff --git a/age/keysource_test.go b/age/keysource_test.go new file mode 100644 index 000000000..a51f94667 --- /dev/null +++ b/age/keysource_test.go @@ -0,0 +1,31 @@ +package age + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAge(t *testing.T) { + assert := assert.New(t) + + key, err := MasterKeyFromRecipient("age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw") + + assert.NoError(err) + assert.Equal("age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw", key.ToString()) + + dataKey := []byte("abcdefghijklmnopqrstuvwxyz123456") + + err = key.Encrypt(dataKey) + assert.NoError(err) + + pwd, err := os.Getwd() + assert.NoError(err) + err = os.Setenv("SOPS_AGE_KEY_DIR", pwd) + assert.NoError(err) + + decryptedKey, err := key.Decrypt() + assert.NoError(err) + assert.Equal(dataKey, decryptedKey) +} From 2741ab530a7033c02eaa2b88f60c23d2bea92cde Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 26 Jul 2020 22:15:45 -0700 Subject: [PATCH 05/40] Use user config dir instead of home dir as the root for age keys. --- age/keysource.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index d819d2eb6..1cb82859c 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -79,13 +79,13 @@ func (key *MasterKey) Decrypt() ([]byte, error) { ageKeyDir, ok := os.LookupEnv("SOPS_AGE_KEY_DIR") if !ok { - userHomeDir, err := os.UserHomeDir() + userConfigDir, err := os.UserConfigDir() if err != nil { - return nil, fmt.Errorf("home directory could not be determined: %v", err) + return nil, fmt.Errorf("user config directory could not be determined: %v", err) } - ageKeyDir = filepath.Join(userHomeDir, ".sops", "age") + ageKeyDir = filepath.Join(userConfigDir, ".sops", "age") } path := filepath.Join(ageKeyDir, fmt.Sprintf("%s.key", key.Recipient)) From d9b196c87c4b72dab41aff197583a8787d995ed7 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Tue, 28 Jul 2020 03:32:03 -0700 Subject: [PATCH 06/40] Determine age package path using current file rather than pwd. --- age/keysource_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/age/keysource_test.go b/age/keysource_test.go index a51f94667..b39d4868e 100644 --- a/age/keysource_test.go +++ b/age/keysource_test.go @@ -2,6 +2,8 @@ package age import ( "os" + "path" + "runtime" "testing" "github.com/stretchr/testify/assert" @@ -20,9 +22,8 @@ func TestAge(t *testing.T) { err = key.Encrypt(dataKey) assert.NoError(err) - pwd, err := os.Getwd() - assert.NoError(err) - err = os.Setenv("SOPS_AGE_KEY_DIR", pwd) + _, filename, _, _ := runtime.Caller(0) + err = os.Setenv("SOPS_AGE_KEY_DIR", path.Dir(filename)) assert.NoError(err) decryptedKey, err := key.Decrypt() From 5c171c800c8fc2cadecf0573c2a5b556ac4d08da Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Tue, 28 Jul 2020 03:32:22 -0700 Subject: [PATCH 07/40] Don't swallow potential errors from os.Stat. --- age/keysource.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index 1cb82859c..cd3e824de 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -92,12 +92,12 @@ func (key *MasterKey) Decrypt() ([]byte, error) { _, err := os.Stat(path) - if os.IsNotExist(err) { - return nil, fmt.Errorf("no private key found at %s", path) - } - file, err := os.Open(path) + if err != nil { + return nil, fmt.Errorf("no private key found at %s: %s", path, err) + } + defer file.Close() scanner := bufio.NewScanner(file) From 617db437def269a9b3a62b30f89d832a64741783 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 2 Aug 2020 22:55:48 -0700 Subject: [PATCH 08/40] Use a single keys.txt file for age private keys. --- ...uprpmy89nr83ltx74tqdpszlw.key => keys.txt} | 0 age/keysource.go | 37 +++++++++++++------ age/keysource_test.go | 2 +- 3 files changed, 26 insertions(+), 13 deletions(-) rename age/{age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw.key => keys.txt} (100%) diff --git a/age/age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw.key b/age/keys.txt similarity index 100% rename from age/age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw.key rename to age/keys.txt diff --git a/age/keysource.go b/age/keysource.go index cd3e824de..d63df0e73 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -27,10 +27,10 @@ func (key *MasterKey) Encrypt(datakey []byte) error { buffer := &bytes.Buffer{} if key.parsedRecipient == nil { - parsedRecipient, err := age.ParseX25519Recipient(key.Recipient) + parsedRecipient, err := parseRecipient(key.Recipient) if err != nil { - return fmt.Errorf("failed to parse input as Bech32-encoded age public key: %v", err) + return err } key.parsedRecipient = parsedRecipient @@ -76,7 +76,7 @@ func (key *MasterKey) SetEncryptedDataKey(enc []byte) { // Decrypt decrypts the EncryptedKey field with the age identity and returns the result. func (key *MasterKey) Decrypt() ([]byte, error) { - ageKeyDir, ok := os.LookupEnv("SOPS_AGE_KEY_DIR") + ageKeyFile, ok := os.LookupEnv("SOPS_AGE_KEY_FILE") if !ok { userConfigDir, err := os.UserConfigDir() @@ -85,17 +85,19 @@ func (key *MasterKey) Decrypt() ([]byte, error) { return nil, fmt.Errorf("user config directory could not be determined: %v", err) } - ageKeyDir = filepath.Join(userConfigDir, ".sops", "age") + ageKeyFile = filepath.Join(userConfigDir, ".sops", "age", "keys.txt") } - path := filepath.Join(ageKeyDir, fmt.Sprintf("%s.key", key.Recipient)) + _, err := os.Stat(ageKeyFile) - _, err := os.Stat(path) + if err != nil { + return nil, err + } - file, err := os.Open(path) + file, err := os.Open(ageKeyFile) if err != nil { - return nil, fmt.Errorf("no private key found at %s: %s", path, err) + return nil, fmt.Errorf("no key file found at %s: %s", ageKeyFile, err) } defer file.Close() @@ -114,17 +116,17 @@ func (key *MasterKey) Decrypt() ([]byte, error) { } if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error scanning lines in age private key file: %v", err) + return nil, fmt.Errorf("error scanning lines in age key file: %v", err) } if privateKey == "" { - return nil, fmt.Errorf("no age private key found in file at: %v", path) + return nil, fmt.Errorf("no age private key found in file at: %v", ageKeyFile) } parsedIdentity, err := age.ParseX25519Identity(string(privateKey)) if err != nil { - return nil, fmt.Errorf("failed to parse private key as age X25519Identity at %s: %v", path, err) + return nil, fmt.Errorf("failed to parse private key as age X25519Identity at %s: %v", ageKeyFile, err) } buffer := &bytes.Buffer{} @@ -183,7 +185,7 @@ func MasterKeysFromRecipients(commaSeparatedRecipients string) ([]*MasterKey, er // MasterKeyFromRecipient takes a Bech32-encoded public key and returns a new MasterKey. func MasterKeyFromRecipient(recipient string) (*MasterKey, error) { - parsedRecipient, err := age.ParseX25519Recipient(recipient) + parsedRecipient, err := parseRecipient(recipient) if err != nil { return nil, err @@ -194,3 +196,14 @@ func MasterKeyFromRecipient(recipient string) (*MasterKey, error) { parsedRecipient: parsedRecipient, }, nil } + +// parseRecipient attempts to parse a string containing an encoded age public key +func parseRecipient(recipient string) (*age.X25519Recipient, error) { + parsedRecipient, err := age.ParseX25519Recipient(recipient) + + if err != nil { + return nil, fmt.Errorf("failed to parse input as Bech32-encoded age public key: %v", err) + } + + return parsedRecipient, nil +} diff --git a/age/keysource_test.go b/age/keysource_test.go index b39d4868e..43bd07dd4 100644 --- a/age/keysource_test.go +++ b/age/keysource_test.go @@ -23,7 +23,7 @@ func TestAge(t *testing.T) { assert.NoError(err) _, filename, _, _ := runtime.Caller(0) - err = os.Setenv("SOPS_AGE_KEY_DIR", path.Dir(filename)) + err = os.Setenv("SOPS_AGE_KEY_FILE", path.Join(path.Dir(filename), "keys.txt")) assert.NoError(err) decryptedKey, err := key.Decrypt() From 7f7ecbc18ec08c709f1f99ec7abb10943cc45de0 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 2 Aug 2020 23:17:49 -0700 Subject: [PATCH 09/40] Try decrypting with all possible keys in the keyfile. --- age/keysource.go | 114 +++++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index d63df0e73..d5c1a1175 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -5,6 +5,7 @@ import ( "bytes" "fmt" "io" + "io/ioutil" "os" "path/filepath" "strings" @@ -12,6 +13,8 @@ import ( "filippo.io/age" ) +const privateKeySizeLimit = 1 << 24 // 16 MiB + // MasterKey is an age key used to encrypt and decrypt sops' data key. type MasterKey struct { Identity string // a Bech32-encoded private key @@ -85,64 +88,35 @@ func (key *MasterKey) Decrypt() ([]byte, error) { return nil, fmt.Errorf("user config directory could not be determined: %v", err) } - ageKeyFile = filepath.Join(userConfigDir, ".sops", "age", "keys.txt") + ageKeyFile = filepath.Join(userConfigDir, "sops", "age", "keys.txt") } - _, err := os.Stat(ageKeyFile) + identities, err := parseIdentitiesFile(ageKeyFile) if err != nil { return nil, err } - file, err := os.Open(ageKeyFile) - - if err != nil { - return nil, fmt.Errorf("no key file found at %s: %s", ageKeyFile, err) - } - - defer file.Close() - - scanner := bufio.NewScanner(file) + var buffer *bytes.Buffer - var privateKey string + for _, identity := range identities { + buffer = &bytes.Buffer{} + reader := bytes.NewReader([]byte(key.EncryptedKey)) - for scanner.Scan() { - line := scanner.Text() + r, err := age.Decrypt(reader, identity) - if strings.HasPrefix(line, "AGE-SECRET-KEY") { - privateKey = line - break + if err != nil { + continue } - } - - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error scanning lines in age key file: %v", err) - } - - if privateKey == "" { - return nil, fmt.Errorf("no age private key found in file at: %v", ageKeyFile) - } - - parsedIdentity, err := age.ParseX25519Identity(string(privateKey)) - - if err != nil { - return nil, fmt.Errorf("failed to parse private key as age X25519Identity at %s: %v", ageKeyFile, err) - } - - buffer := &bytes.Buffer{} - reader := bytes.NewReader([]byte(key.EncryptedKey)) - r, err := age.Decrypt(reader, parsedIdentity) - - if err != nil { - return nil, fmt.Errorf("failed to open encrypted data key: %v", err) - } + if _, err := io.Copy(buffer, r); err != nil { + continue + } - if _, err := io.Copy(buffer, r); err != nil { - return nil, fmt.Errorf("failed to read encrypted data key: %v", err) + return buffer.Bytes(), nil } - return buffer.Bytes(), nil + return nil, fmt.Errorf("no age identity found in %q that could decrypt the data", ageKeyFile) } // NeedsRotation returns whether the data key needs to be rotated or not. @@ -207,3 +181,57 @@ func parseRecipient(recipient string) (*age.X25519Recipient, error) { return parsedRecipient, nil } + +// parseIdentitiesFile parses a file containing age private keys. Derived from +// https://github.com/FiloSottile/age/blob/189041b668629795593766bcb8d3f70ee248b842/cmd/age/parse.go +// but should be replaced with a library function if a future version of the age library exposes +// this functionality. +func parseIdentitiesFile(name string) ([]age.Identity, error) { + f, err := os.Open(name) + if err != nil { + return nil, fmt.Errorf("failed to open file: %v", err) + } + defer f.Close() + + contents, err := ioutil.ReadAll(io.LimitReader(f, privateKeySizeLimit)) + if err != nil { + return nil, fmt.Errorf("failed to read %q: %v", name, err) + } + if len(contents) == privateKeySizeLimit { + return nil, fmt.Errorf("failed to read %q: file too long", name) + } + + var ids []age.Identity + var ageParsingError error + scanner := bufio.NewScanner(bytes.NewReader(contents)) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "#") || line == "" { + continue + } + if strings.HasPrefix(line, "-----BEGIN") { + ageParsingError = fmt.Errorf("sops does not yet support SSH keys via age. SSH key found in file at %q", name) + continue + } + if ageParsingError != nil { + continue + } + i, err := age.ParseX25519Identity(line) + if err != nil { + ageParsingError = fmt.Errorf("malformed secret keys file %q: %v", name, err) + continue + } + ids = append(ids, i) + } + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("failed to read %q: %v", name, err) + } + if ageParsingError != nil { + return nil, ageParsingError + } + + if len(ids) == 0 { + return nil, fmt.Errorf("no secret keys found in %q", name) + } + return ids, nil +} From ade5692dcc1c55846a5dbaade5e4241d977bc92b Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 2 Aug 2020 23:47:53 -0700 Subject: [PATCH 10/40] Document age usage. --- README.rst | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 603356c21..40b5ad129 100644 --- a/README.rst +++ b/README.rst @@ -2,7 +2,7 @@ SOPS: Secrets OPerationS ======================== **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. +formats and encrypts with AWS KMS, GCP KMS, Azure Key Vault, age, and PGP. (`demo `_) .. image:: https://i.imgur.com/X0TM5NI.gif @@ -164,6 +164,32 @@ Given that, the only command a ``sops`` user needs is: encrypted if modified, and saved back to its original location. All of these steps, apart from the actual editing, are transparent to the user. +Encrypting using age +~~~~~~~~~~~~~~~~~~~~ + +`age`_ is a simple, modern, and secure tool for +encrypting files. It's recommended to use age over PGP, if possible. + +You can encrypt a file for one or more age recipients (comma separated) using +the ``--age`` option or the **SOPS_AGE_RECIPIENTS** environment variable: + +.. code:: bash + + $ sops --age age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw test.yaml > test.enc.yaml + +When decrypting a file with the corresponding identity, sops will look for a +text file name ``keys.txt`` located in a ``sops`` subdirectory of your user +configuration directory. On Linux, this would be ``$XDG_CONFIG_HOME/sops/keys.txt``. +On macOS, this would be ``$HOME/Library/Application Support/sops/keys.txt``. On +Windows, this would be ``%AppData%\sops\keys.txt``. You can specify the location +of this file manually by setting the environment variable **SOPS_AGE_KEY_FILE**. + +The contents of this key file should be a list of age X25519 identities, one +per line. Lines beginning with ``#`` are considered comments and ignored. Each +identity will be tried in sequence until one is able to decrypt the data. + +Encrypting with SSH keys via age is not yet supported by sops. + Test with the dev PGP key ~~~~~~~~~~~~~~~~~~~~~~~~~ From a66a0a84297062392bb90a8a8e0018b373c83c54 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 2 Aug 2020 23:51:31 -0700 Subject: [PATCH 11/40] Reorder README sections and fix RST link. --- README.rst | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/README.rst b/README.rst index 40b5ad129..0ec65b7e9 100644 --- a/README.rst +++ b/README.rst @@ -164,10 +164,24 @@ Given that, the only command a ``sops`` user needs is: encrypted if modified, and saved back to its original location. All of these steps, apart from the actual editing, are transparent to the user. +Test with the dev PGP key +~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you want to test **sops** without having to do a bunch of setup, you can use +the example files and pgp key provided with the repository:: + + $ git clone https://github.com/mozilla/sops.git + $ cd sops + $ gpg --import pgp/sops_functional_tests_key.asc + $ sops example.yaml + +This last step will decrypt ``example.yaml`` using the test private key. + + Encrypting using age ~~~~~~~~~~~~~~~~~~~~ -`age`_ is a simple, modern, and secure tool for +`age `_ is a simple, modern, and secure tool for encrypting files. It's recommended to use age over PGP, if possible. You can encrypt a file for one or more age recipients (comma separated) using @@ -190,19 +204,6 @@ identity will be tried in sequence until one is able to decrypt the data. Encrypting with SSH keys via age is not yet supported by sops. -Test with the dev PGP key -~~~~~~~~~~~~~~~~~~~~~~~~~ - -If you want to test **sops** without having to do a bunch of setup, you can use -the example files and pgp key provided with the repository:: - - $ git clone https://github.com/mozilla/sops.git - $ cd sops - $ gpg --import pgp/sops_functional_tests_key.asc - $ sops example.yaml - -This last step will decrypt ``example.yaml`` using the test private key. - Encrypting using GCP KMS ~~~~~~~~~~~~~~~~~~~~~~~~ From 6a6a9363da2807149692506bd3393102e49b80fc Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 9 Aug 2020 00:34:37 -0700 Subject: [PATCH 12/40] Use more concise style for constructing map. --- age/keysource.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index d5c1a1175..725a2fb2a 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -131,10 +131,7 @@ func (key *MasterKey) ToString() string { // ToMap converts the MasterKey to a map for serialization purposes. func (key *MasterKey) ToMap() map[string]interface{} { - out := make(map[string]interface{}) - out["recipient"] = key.Recipient - out["enc"] = key.EncryptedKey - return out + return map[string]interface{}{"recipient": key.Recipient, "enc": key.EncryptedKey} } // MasterKeysFromRecipients takes a comma-separated list of Bech32-encoded public keys and returns a From 1dbea5d6bec87ba8f053405c0aeceb0432fea288 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 9 Aug 2020 00:34:44 -0700 Subject: [PATCH 13/40] Fix whitespace errors. --- keyservice/keyservice.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/keyservice/keyservice.proto b/keyservice/keyservice.proto index f2b7faa90..1d91a5709 100644 --- a/keyservice/keyservice.proto +++ b/keyservice/keyservice.proto @@ -7,7 +7,7 @@ message Key { GcpKmsKey gcp_kms_key = 3; AzureKeyVaultKey azure_keyvault_key = 4; VaultKey vault_key = 5; - AgeKey age_key = 6; + AgeKey age_key = 6; } } @@ -39,7 +39,7 @@ message AzureKeyVaultKey { } message AgeKey { - string recipient = 1; + string recipient = 1; } message EncryptRequest { From 6068838aa32d7c4f6e207ffae0d50f587d7951cb Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Sun, 9 Aug 2020 00:50:45 -0700 Subject: [PATCH 14/40] Update go.mod/go.sum. --- go.mod | 1 - go.sum | 12 +----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 6b95c902f..63b375811 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,6 @@ require ( github.com/sirupsen/logrus v1.4.2 github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 // indirect github.com/stretchr/testify v1.5.1 - github.com/vektra/mockery v1.1.2 // indirect go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b diff --git a/go.sum b/go.sum index 393a3a15b..072d419ef 100644 --- a/go.sum +++ b/go.sum @@ -269,9 +269,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/vektra/mockery v1.1.2 h1:uc0Yn67rJpjt8U/mAZimdCKn9AeA97BOkjpmtBSlfP4= -github.com/vektra/mockery v1.1.2/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a h1:N7VD+PwpJME2ZfQT8+ejxwA4Ow10IkGbU0MGf94ll8k= go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a/go.mod h1:YDKUvO0b//78PaaEro6CAPH6NqohCmL2Cwju5XI2HoE= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -298,8 +295,6 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -328,7 +323,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -368,11 +362,6 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e h1:ssd5ulOvVWlh4kDSUF2SqzmMeWfjmwDXM+uGw/aQjRE= -golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= @@ -435,6 +424,7 @@ gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bl gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= From 50a89c82931425d927e8f10ccff7bcf92c3ee4e5 Mon Sep 17 00:00:00 2001 From: Cole Mickens Date: Fri, 7 Aug 2020 01:58:17 -0700 Subject: [PATCH 15/40] age: .sops.yaml support --- age/keysource.go | 16 ++++++++++++++-- config/config.go | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index 725a2fb2a..254cbfb6f 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -11,8 +11,16 @@ import ( "strings" "filippo.io/age" + "github.com/sirupsen/logrus" + "go.mozilla.org/sops/v3/logging" ) +var log *logrus.Logger + +func init() { + log = logging.NewLogger("AGE") +} + const privateKeySizeLimit = 1 << 24 // 16 MiB // MasterKey is an age key used to encrypt and decrypt sops' data key. @@ -33,6 +41,7 @@ func (key *MasterKey) Encrypt(datakey []byte) error { parsedRecipient, err := parseRecipient(key.Recipient) if err != nil { + log.WithField("recipient", key.parsedRecipient).Error("Encryption failed") return err } @@ -40,20 +49,23 @@ func (key *MasterKey) Encrypt(datakey []byte) error { } w, err := age.Encrypt(buffer, key.parsedRecipient) - if err != nil { return fmt.Errorf("failed to open file for encrypting sops data key with age: %v", err) } if _, err := w.Write(datakey); err != nil { + log.WithField("recipient", key.parsedRecipient).Error("Encryption failed") return fmt.Errorf("failed to encrypt sops data key with age: %v", err) } if err := w.Close(); err != nil { + log.WithField("recipient", key.parsedRecipient).Error("Encryption failed") return fmt.Errorf("failed to close file for encrypting sops data key with age: %v", err) } - + key.EncryptedKey = buffer.String() + + log.WithField("recipient", key.parsedRecipient).Info("Encryption succeeded") return nil } diff --git a/config/config.go b/config/config.go index 67a06cdda..dc62eee05 100644 --- a/config/config.go +++ b/config/config.go @@ -13,6 +13,7 @@ import ( "github.com/mozilla-services/yaml" "github.com/sirupsen/logrus" "go.mozilla.org/sops/v3" + "go.mozilla.org/sops/v3/age" "go.mozilla.org/sops/v3/azkv" "go.mozilla.org/sops/v3/gcpkms" "go.mozilla.org/sops/v3/hcvault" @@ -71,6 +72,7 @@ type keyGroup struct { GCPKMS []gcpKmsKey `yaml:"gcp_kms"` AzureKV []azureKVKey `yaml:"azure_keyvault"` Vault []string `yaml:"hc_vault"` + Age []string `yaml:"age"` PGP []string } @@ -109,6 +111,7 @@ type creationRule struct { PathRegex string `yaml:"path_regex"` KMS string AwsProfile string `yaml:"aws_profile"` + Age string `yaml:"age"` PGP string GCPKMS string `yaml:"gcp_kms"` AzureKeyVault string `yaml:"azure_keyvault"` @@ -147,6 +150,13 @@ func getKeyGroupsFromCreationRule(cRule *creationRule, kmsEncryptionContext map[ if len(cRule.KeyGroups) > 0 { for _, group := range cRule.KeyGroups { var keyGroup sops.KeyGroup + for _, k := range group.Age { + key, err := age.MasterKeyFromRecipient(k) + if err != nil { + return nil, err + } + keyGroup = append(keyGroup, key) + } for _, k := range group.PGP { keyGroup = append(keyGroup, pgp.NewMasterKeyFromFingerprint(k)) } @@ -170,6 +180,14 @@ func getKeyGroupsFromCreationRule(cRule *creationRule, kmsEncryptionContext map[ } } else { var keyGroup sops.KeyGroup + ageKeys, err := age.MasterKeysFromRecipients(cRule.Age) + if err != nil { + return nil, err + } else { + for _, ak := range ageKeys { + keyGroup = append(keyGroup, ak) + } + } for _, k := range pgp.MasterKeysFromFingerprintString(cRule.PGP) { keyGroup = append(keyGroup, k) } From 8f6271f5c859204cf8c8d7e174552fd50d3a7623 Mon Sep 17 00:00:00 2001 From: Cole Mickens Date: Sun, 16 Aug 2020 15:12:54 -0700 Subject: [PATCH 16/40] age: MasterKeysFromRecipients: gracefully handle empty string --- age/keysource.go | 8 ++++++-- age/keysource_test.go | 11 +++++++++++ config/config.go | 14 ++++++++------ 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index 254cbfb6f..7ef038ddf 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -62,9 +62,9 @@ func (key *MasterKey) Encrypt(datakey []byte) error { log.WithField("recipient", key.parsedRecipient).Error("Encryption failed") return fmt.Errorf("failed to close file for encrypting sops data key with age: %v", err) } - + key.EncryptedKey = buffer.String() - + log.WithField("recipient", key.parsedRecipient).Info("Encryption succeeded") return nil @@ -149,6 +149,10 @@ func (key *MasterKey) ToMap() map[string]interface{} { // MasterKeysFromRecipients takes a comma-separated list of Bech32-encoded public keys and returns a // slice of new MasterKeys. func MasterKeysFromRecipients(commaSeparatedRecipients string) ([]*MasterKey, error) { + if commaSeparatedRecipients == "" { + // otherwise Split returns [""] and MasterKeyFromRecipient is unhappy + return make([]*MasterKey, 0), nil + } recipients := strings.Split(commaSeparatedRecipients, ",") var keys []*MasterKey diff --git a/age/keysource_test.go b/age/keysource_test.go index 43bd07dd4..51fc91519 100644 --- a/age/keysource_test.go +++ b/age/keysource_test.go @@ -9,6 +9,17 @@ import ( "github.com/stretchr/testify/assert" ) +func TestMasterKeysFromRecipientsEmpty(t *testing.T) { + assert := assert.New(t) + + commaSeparatedRecipients := "" + recipients, err := MasterKeysFromRecipients(commaSeparatedRecipients) + + assert.NoError(err) + + assert.Equal(recipients, make([]*MasterKey,0)) +} + func TestAge(t *testing.T) { assert := assert.New(t) diff --git a/config/config.go b/config/config.go index dc62eee05..91f31df3c 100644 --- a/config/config.go +++ b/config/config.go @@ -180,12 +180,14 @@ func getKeyGroupsFromCreationRule(cRule *creationRule, kmsEncryptionContext map[ } } else { var keyGroup sops.KeyGroup - ageKeys, err := age.MasterKeysFromRecipients(cRule.Age) - if err != nil { - return nil, err - } else { - for _, ak := range ageKeys { - keyGroup = append(keyGroup, ak) + if cRule.Age != "" { + ageKeys, err := age.MasterKeysFromRecipients(cRule.Age) + if err != nil { + return nil, err + } else { + for _, ak := range ageKeys { + keyGroup = append(keyGroup, ak) + } } } for _, k := range pgp.MasterKeysFromFingerprintString(cRule.PGP) { From e9acafced7cb0e239edecbb597d2a65bbdc2e550 Mon Sep 17 00:00:00 2001 From: Jimmy Cuadra Date: Mon, 21 Sep 2020 13:00:36 -0700 Subject: [PATCH 17/40] Update to age 1.0.0-beta5. --- age/keysource.go | 91 ++++++++++-------------------------------------- go.mod | 2 +- go.sum | 8 ++--- 3 files changed, 21 insertions(+), 80 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index 7ef038ddf..48dff56d1 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -1,11 +1,9 @@ package age import ( - "bufio" "bytes" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strings" @@ -91,7 +89,7 @@ func (key *MasterKey) SetEncryptedDataKey(enc []byte) { // Decrypt decrypts the EncryptedKey field with the age identity and returns the result. func (key *MasterKey) Decrypt() ([]byte, error) { - ageKeyFile, ok := os.LookupEnv("SOPS_AGE_KEY_FILE") + ageKeyFilePath, ok := os.LookupEnv("SOPS_AGE_KEY_FILE") if !ok { userConfigDir, err := os.UserConfigDir() @@ -100,35 +98,36 @@ func (key *MasterKey) Decrypt() ([]byte, error) { return nil, fmt.Errorf("user config directory could not be determined: %v", err) } - ageKeyFile = filepath.Join(userConfigDir, "sops", "age", "keys.txt") + ageKeyFilePath = filepath.Join(userConfigDir, "sops", "age", "keys.txt") } - identities, err := parseIdentitiesFile(ageKeyFile) + ageKeyFile, err := os.Open(ageKeyFilePath) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to open file: %v", err) } - var buffer *bytes.Buffer + defer ageKeyFile.Close() - for _, identity := range identities { - buffer = &bytes.Buffer{} - reader := bytes.NewReader([]byte(key.EncryptedKey)) + identities, err := age.ParseIdentities(ageKeyFile) - r, err := age.Decrypt(reader, identity) + if err != nil { + return nil, err + } - if err != nil { - continue - } + buffer := &bytes.Buffer{} + reader := bytes.NewReader([]byte(key.EncryptedKey)) + r, err := age.Decrypt(reader, identities...) - if _, err := io.Copy(buffer, r); err != nil { - continue - } + if err != nil { + return nil, fmt.Errorf("no age identity found in %q that could decrypt the data", ageKeyFilePath) + } - return buffer.Bytes(), nil + if _, err := io.Copy(buffer, r); err != nil { + return nil, fmt.Errorf("failed to copy decrypted data into bytes.Buffer") } - return nil, fmt.Errorf("no age identity found in %q that could decrypt the data", ageKeyFile) + return buffer.Bytes(), nil } // NeedsRotation returns whether the data key needs to be rotated or not. @@ -194,57 +193,3 @@ func parseRecipient(recipient string) (*age.X25519Recipient, error) { return parsedRecipient, nil } - -// parseIdentitiesFile parses a file containing age private keys. Derived from -// https://github.com/FiloSottile/age/blob/189041b668629795593766bcb8d3f70ee248b842/cmd/age/parse.go -// but should be replaced with a library function if a future version of the age library exposes -// this functionality. -func parseIdentitiesFile(name string) ([]age.Identity, error) { - f, err := os.Open(name) - if err != nil { - return nil, fmt.Errorf("failed to open file: %v", err) - } - defer f.Close() - - contents, err := ioutil.ReadAll(io.LimitReader(f, privateKeySizeLimit)) - if err != nil { - return nil, fmt.Errorf("failed to read %q: %v", name, err) - } - if len(contents) == privateKeySizeLimit { - return nil, fmt.Errorf("failed to read %q: file too long", name) - } - - var ids []age.Identity - var ageParsingError error - scanner := bufio.NewScanner(bytes.NewReader(contents)) - for scanner.Scan() { - line := scanner.Text() - if strings.HasPrefix(line, "#") || line == "" { - continue - } - if strings.HasPrefix(line, "-----BEGIN") { - ageParsingError = fmt.Errorf("sops does not yet support SSH keys via age. SSH key found in file at %q", name) - continue - } - if ageParsingError != nil { - continue - } - i, err := age.ParseX25519Identity(line) - if err != nil { - ageParsingError = fmt.Errorf("malformed secret keys file %q: %v", name, err) - continue - } - ids = append(ids, i) - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("failed to read %q: %v", name, err) - } - if ageParsingError != nil { - return nil, ageParsingError - } - - if len(ids) == 0 { - return nil, fmt.Errorf("no secret keys found in %q", name) - } - return ids, nil -} diff --git a/go.mod b/go.mod index 63b375811..e7c39f9a6 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.13 require ( cloud.google.com/go v0.43.0 - filippo.io/age v1.0.0-beta4 + filippo.io/age v1.0.0-beta5 github.com/Azure/azure-sdk-for-go v31.2.0+incompatible github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Azure/go-autorest/autorest v0.9.0 diff --git a/go.sum b/go.sum index 072d419ef..197274951 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,8 @@ cloud.google.com/go v0.43.0 h1:banaiRPAM8kUVYneOSkhgcDsLzEvL25FinuiSZaH/2w= cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= -filippo.io/age v1.0.0-beta4 h1:czSjaSa0owsI5gw/cE9yI/mfTiuhgYjozHI96v0PVJo= -filippo.io/age v1.0.0-beta4/go.mod h1:TOa3exZvzRCLfjmbJGsqwSQ0HtWjJfTTCQnQsNCC4E0= +filippo.io/age v1.0.0-beta5 h1:H3R+VF81f69NdAQhBOSviEtgUd1cZRS1URhUlm2oXjw= +filippo.io/age v1.0.0-beta5/go.mod h1:TOa3exZvzRCLfjmbJGsqwSQ0HtWjJfTTCQnQsNCC4E0= github.com/Azure/azure-sdk-for-go v31.2.0+incompatible h1:kZFnTLmdQYNGfakatSivKHUfUnDZhqNdchHD4oIhp5k= github.com/Azure/azure-sdk-for-go v31.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= @@ -280,10 +280,6 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= From 8acbe730b2bc81f52adc1e814f25399562a3aeb3 Mon Sep 17 00:00:00 2001 From: AJ Bahnken Date: Thu, 24 Sep 2020 12:26:16 -0700 Subject: [PATCH 18/40] typo fix for deprecation warning in getKeyFromKeyServer --- pgp/keysource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgp/keysource.go b/pgp/keysource.go index fd092339c..3a126484a 100644 --- a/pgp/keysource.go +++ b/pgp/keysource.go @@ -87,7 +87,7 @@ func (key *MasterKey) encryptWithGPGBinary(dataKey []byte) error { } func getKeyFromKeyServer(fingerprint string) (openpgp.Entity, error) { - log.Warn("Deprecation Warning: GPG key fetching from a keyserver witihin sops will be removed in a future version of sops. See https://github.com/mozilla/sops/issues/727 for more information.") + log.Warn("Deprecation Warning: GPG key fetching from a keyserver within sops will be removed in a future version of sops. See https://github.com/mozilla/sops/issues/727 for more information.") url := fmt.Sprintf("https://keys.openpgp.org/vks/v1/by-fingerprint/%s", fingerprint) resp, err := http.Get(url) From 13d64c94ebfbd88111dcc70de5244ea32dea3ca9 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 7 Oct 2020 11:58:28 +0200 Subject: [PATCH 19/40] Bump YAML library version, and add test for YAML library. (#754) --- go.mod | 2 +- go.sum | 3 ++ stores/yaml/store_test.go | 59 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index e7c39f9a6..1b06a8d15 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/lib/pq v1.2.0 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-wordwrap v1.0.0 - github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c + github.com/mozilla-services/yaml v0.0.0-20201006214821-a130ed024dcf github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect diff --git a/go.sum b/go.sum index 197274951..1bb1850bc 100644 --- a/go.sum +++ b/go.sum @@ -211,6 +211,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c h1:yE1NxRAZA3wF0laDWECtOe2J0tFjSHUI6MXXbMif+QY= github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= +github.com/mozilla-services/yaml v0.0.0-20201006214821-a130ed024dcf h1:Lcffxn0MTcVD0v/kBCul62VDj0st4zxBSahSf03hGEc= +github.com/mozilla-services/yaml v0.0.0-20201006214821-a130ed024dcf/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -271,6 +273,7 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a h1:N7VD+PwpJME2ZfQT8+ejxwA4Ow10IkGbU0MGf94ll8k= go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a/go.mod h1:YDKUvO0b//78PaaEro6CAPH6NqohCmL2Cwju5XI2HoE= +go.mozilla.org/sops v0.0.0-20190912205235-14a22d7a7060 h1:KnOZgR0z89tCwGympfPkpzXdlCmhksUP5ddQ+Iqo1FU= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= diff --git a/stores/yaml/store_test.go b/stores/yaml/store_test.go index bed993507..fdffdc7dc 100644 --- a/stores/yaml/store_test.go +++ b/stores/yaml/store_test.go @@ -38,6 +38,38 @@ var BRANCHES = sops.TreeBranches{ }, } +var COMMENT_1 = []byte(`a: + b: null + # foo +`) + +var COMMENT_2 = []byte(`a: + # foo + b: null +`) + +var COMMENT_3_IN = []byte(`## Configuration for prometheus-node-exporter subchart +## +prometheus-node-exporter: + podLabels: + ## Add the 'node-exporter' label to be used by serviceMonitor to match standard common usage in rules and grafana dashboards + ## + + jobLabel: node-exporter + extraArgs: + - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/) + - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$ +`) +var COMMENT_3_OUT = []byte(`prometheus-node-exporter: + podLabels: + ## Add the 'node-exporter' label to be used by serviceMonitor to match standard common usage in rules and grafana dashboards + ## + jobLabel: node-exporter + extraArgs: + - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/) + - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$ +`) + func TestUnmarshalMetadataFromNonSOPSFile(t *testing.T) { data := []byte(`hello: 2`) _, err := (&Store{}).LoadEncryptedFile(data) @@ -49,3 +81,30 @@ func TestLoadPlainFile(t *testing.T) { assert.Nil(t, err) assert.Equal(t, BRANCHES, branches) } + +func TestComment1(t *testing.T) { + // First iteration: load and store + branches, err := (&Store{}).LoadPlainFile(COMMENT_1) + assert.Nil(t, err) + bytes, err := (&Store{}).EmitPlainFile(branches) + assert.Nil(t, err) + assert.Equal(t, COMMENT_1, bytes) +} + +func TestComment2(t *testing.T) { + // First iteration: load and store + branches, err := (&Store{}).LoadPlainFile(COMMENT_2) + assert.Nil(t, err) + bytes, err := (&Store{}).EmitPlainFile(branches) + assert.Nil(t, err) + assert.Equal(t, COMMENT_2, bytes) +} + +func TestComment3(t *testing.T) { + // First iteration: load and store + branches, err := (&Store{}).LoadPlainFile(COMMENT_3_IN) + assert.Nil(t, err) + bytes, err := (&Store{}).EmitPlainFile(branches) + assert.Nil(t, err) + assert.Equal(t, COMMENT_3_OUT, bytes) +} From b1d253e7b9523c5d2f7c604ff060a152eec4a9fa Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 7 Oct 2020 18:10:51 +0200 Subject: [PATCH 20/40] Do not discard comments at beginning of YAML documents (#757) * Allow to preserve comments at beginning of YAML document. * Extend functional tests. * Update changelog. --- CHANGELOG.rst | 11 +++++++++++ functional-tests/res/comments.enc.yaml | 9 ++++++--- functional-tests/res/comments.yaml | 1 + .../res/comments_unencrypted_comments.yaml | 1 + functional-tests/src/lib.rs | 3 +++ go.mod | 2 +- go.sum | 2 ++ stores/yaml/store_test.go | 11 +++++++++-- 8 files changed, 34 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 48e777227..e8c78fd88 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,17 @@ Changelog ========= +Develop branch +-------------- + +Changes: + + * Comments at the beginning of YAML documents are now no longer discarded (#756) + +Bug fixes: + + * Fix several problems with YAML comment handling described in #695 (#754) + 3.6.1 ----- Features: diff --git a/functional-tests/res/comments.enc.yaml b/functional-tests/res/comments.enc.yaml index f28ea5d23..7b386184e 100644 --- a/functional-tests/res/comments.enc.yaml +++ b/functional-tests/res/comments.enc.yaml @@ -1,3 +1,4 @@ +#ENC[AES256_GCM,data:IYA+b4ORDq8u9CBQolipWD4HRqoZyA==,iv:F8ldQqGng+WptHuBkFtjrGM+7sRZCsvd0FHq98lrpAE=,tag:ZHbLU9+CELinf5PhhuIzSQ==,type:comment] lorem: ENC[AES256_GCM,data:PhmSdTs=,iv:J5ugEWq6RfyNx+5zDXvcTdoQ18YYZkqesDED7LNzou4=,tag:0Qrom6J6aUnZMZzGz5XCxw==,type:str] #ENC[AES256_GCM,data:HiHCasVRzWUiFxKb3X/AcEeM,iv:bmNg+T91dqGk/CEtVH+FDC53osDCEPmWmJKpLyAU5OM=,tag:bTLDYxQSAfYDCBYccoUokQ==,type:comment] dolor: ENC[AES256_GCM,data:IgvT,iv:wtPNYbDTARFE810PH6ldOLzCDcAjkB/dzPsZjpgHcko=,tag:zwE8P+AwO1hrHkgF6pTbZw==,type:str] @@ -5,8 +6,10 @@ sops: kms: [] gcp_kms: [] azure_kv: [] - lastmodified: '2017-08-16T03:41:16Z' - mac: ENC[AES256_GCM,data:3ngUnY2hkK6pkDbCeAnOHsi/M6bLnGk1vkd+EeGyN/efqJZmwH0+9hUdACNnwHzofIR6NbtCGZal+cSCuTGD4eDuqNV+LbwV1/EaaVZj9RktTNXq3STSXxfzYGoHV3NOMtBhq6sYhF0U72nunreCymm3QzOTylAa2HlmRs54axM=,iv:EMXphsMa+ELK8XXX3MDfFJe3jFgXzwCSwjxNR5ah14k=,tag:gakwLdPvwyihj+FkTG/2kQ==,type:str] + hc_vault: [] + age: [] + lastmodified: '2020-10-07T15:49:13Z' + mac: ENC[AES256_GCM,data:2dhyKdHYSynjXPwYrn9356wA7vRKw+T5qwBenI2vZrgthpQBOCQG4M6f7eeH3VLTxB4mN4CAchb25dsNRoGr6A38VruaSSAhPco3Rh4AlvKSvXuhgRnzZvNxE/bnHX1D4K5cdTb4FsJg/Ue1l7UcWrlrv1s3H3SwLHP/nf+suD0=,iv:6xBYURjjaQzlUOKOrs2NWOChiNFZVAGPJZQZ59MwX3o=,tag:uXD5VYme+c8eHcCc5TD2YA==,type:str] pgp: - created_at: '2019-08-29T21:52:32Z' enc: | @@ -24,4 +27,4 @@ sops: -----END PGP MESSAGE----- fp: FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4 unencrypted_suffix: _unencrypted - version: 2.0.9 + version: 3.6.1 diff --git a/functional-tests/res/comments.yaml b/functional-tests/res/comments.yaml index b8761445e..c0a880c91 100644 --- a/functional-tests/res/comments.yaml +++ b/functional-tests/res/comments.yaml @@ -1,3 +1,4 @@ +# first comment in file lorem: ipsum # this-is-a-comment dolor: sit \ No newline at end of file diff --git a/functional-tests/res/comments_unencrypted_comments.yaml b/functional-tests/res/comments_unencrypted_comments.yaml index 86fa3aecc..dbaaa5203 100644 --- a/functional-tests/res/comments_unencrypted_comments.yaml +++ b/functional-tests/res/comments_unencrypted_comments.yaml @@ -1,3 +1,4 @@ +# first comment in file lorem: ENC[AES256_GCM,data:qVz4paM=,iv:0oGsaw71i3wZKmlyDl8uDhQT9XLvJt3oIyx514X44K8=,tag:acbMS613StWo1IVnKK+5uQ==,type:str] # this-is-a-comment dolor: ENC[AES256_GCM,data:21fI,iv:01LXdHZYwLTeyUB1YWIAM6KF8cPPVsw/RuQO+Ab4pgM=,tag:o1xnCIIoccWzdWxB2kZYKg==,type:str] diff --git a/functional-tests/src/lib.rs b/functional-tests/src/lib.rs index 074af4260..756e832f5 100644 --- a/functional-tests/src/lib.rs +++ b/functional-tests/src/lib.rs @@ -421,6 +421,7 @@ b: ba"# .output() .expect("Error running sops"); assert!(output.status.success(), "SOPS didn't return successfully"); + assert!(!String::from_utf8_lossy(&output.stdout).contains("first comment in file"), "Comment was not encrypted"); assert!(!String::from_utf8_lossy(&output.stdout).contains("this-is-a-comment"), "Comment was not encrypted"); } @@ -446,6 +447,7 @@ b: ba"# .output() .expect("Error running sops"); assert!(output.status.success(), "SOPS didn't return successfully"); + assert!(String::from_utf8_lossy(&output.stdout).contains("first comment in file"), "Comment was not decrypted"); assert!(String::from_utf8_lossy(&output.stdout).contains("this-is-a-comment"), "Comment was not decrypted"); } @@ -458,6 +460,7 @@ b: ba"# .output() .expect("Error running sops"); assert!(output.status.success(), "SOPS didn't return successfully"); + assert!(String::from_utf8_lossy(&output.stdout).contains("first comment in file"), "Comment was not decrypted"); assert!(String::from_utf8_lossy(&output.stdout).contains("this-is-a-comment"), "Comment was not decrypted"); } diff --git a/go.mod b/go.mod index 1b06a8d15..849557af5 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/lib/pq v1.2.0 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-wordwrap v1.0.0 - github.com/mozilla-services/yaml v0.0.0-20201006214821-a130ed024dcf + github.com/mozilla-services/yaml v0.0.0-20201007153854-c369669a6625 github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect diff --git a/go.sum b/go.sum index 1bb1850bc..e017155d8 100644 --- a/go.sum +++ b/go.sum @@ -213,6 +213,8 @@ github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c h1:yE1NxRAZA github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= github.com/mozilla-services/yaml v0.0.0-20201006214821-a130ed024dcf h1:Lcffxn0MTcVD0v/kBCul62VDj0st4zxBSahSf03hGEc= github.com/mozilla-services/yaml v0.0.0-20201006214821-a130ed024dcf/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= +github.com/mozilla-services/yaml v0.0.0-20201007153854-c369669a6625 h1:5IeGQzguDQ+EsTR5HE7tMYkZe09mqQ9cDypdKQEB5Kg= +github.com/mozilla-services/yaml v0.0.0-20201007153854-c369669a6625/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= diff --git a/stores/yaml/store_test.go b/stores/yaml/store_test.go index fdffdc7dc..d8ccc4c46 100644 --- a/stores/yaml/store_test.go +++ b/stores/yaml/store_test.go @@ -17,6 +17,10 @@ key2: value2`) var BRANCHES = sops.TreeBranches{ sops.TreeBranch{ + sops.TreeItem{ + Key: sops.Comment{" comment 0"}, + Value: nil, + }, sops.TreeItem{ Key: "key1", Value: "value", @@ -38,7 +42,8 @@ var BRANCHES = sops.TreeBranches{ }, } -var COMMENT_1 = []byte(`a: +var COMMENT_1 = []byte(`# test +a: b: null # foo `) @@ -60,7 +65,9 @@ prometheus-node-exporter: - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/) - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$ `) -var COMMENT_3_OUT = []byte(`prometheus-node-exporter: +var COMMENT_3_OUT = []byte(`## Configuration for prometheus-node-exporter subchart +## +prometheus-node-exporter: podLabels: ## Add the 'node-exporter' label to be used by serviceMonitor to match standard common usage in rules and grafana dashboards ## From d8a64281ae26584906b3ff46ec99caf04bf3349a Mon Sep 17 00:00:00 2001 From: Ed Lim Date: Tue, 20 Oct 2020 16:11:55 -0700 Subject: [PATCH 21/40] Fixing a small typo (#759) Co-authored-by: AJ Bahnken <1144310+ajvb@users.noreply.github.com> From 886c1ee78144be6328f546d3aae09445562aefff Mon Sep 17 00:00:00 2001 From: cloudstarz Date: Thu, 29 Oct 2020 16:00:20 -0700 Subject: [PATCH 22/40] Returning stderr when gpg encrypt fails (#762) Co-authored-by: AJ Bahnken <1144310+ajvb@users.noreply.github.com> --- pgp/keysource.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgp/keysource.go b/pgp/keysource.go index 3a126484a..f025c66a2 100644 --- a/pgp/keysource.go +++ b/pgp/keysource.go @@ -80,7 +80,7 @@ func (key *MasterKey) encryptWithGPGBinary(dataKey []byte) error { cmd.Stderr = &stderr err := cmd.Run() if err != nil { - return err + return fmt.Errorf("gpg binary failed with error: %s, %s", err, stderr.String()) } key.EncryptedKey = stdout.String() return nil From 85d1216aeaddfb0ff626d68239dfe9c931064adc Mon Sep 17 00:00:00 2001 From: Steven Kalt Date: Thu, 12 Nov 2020 16:15:13 -0500 Subject: [PATCH 23/40] Correct markdown link in README.rst to a rst link Specifically, the "SKS Keyserver Network Under Attack" link. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 603356c21..c6bd5aff2 100644 --- a/README.rst +++ b/README.rst @@ -675,7 +675,7 @@ Specify a different GPG key server By default, ``sops`` uses the key server ``keys.openpgp.org`` to retrieve the GPG keys that are not present in the local keyring. -This is no longer configurable. You can learn more about why from this write-up: [SKS Keyserver Network Under Attack](https://gist.github.com/rjhansen/67ab921ffb4084c865b3618d6955275f). +This is no longer configurable. You can learn more about why from this write-up: `SKS Keyserver Network Under Attack `_. Example: place the following in your ``~/.bashrc`` From 84c8fdc3bb221cc03c07f774c04b5c0a69769cfe Mon Sep 17 00:00:00 2001 From: Adrian Utrilla Date: Tue, 29 Dec 2020 15:22:43 +0100 Subject: [PATCH 24/40] Move to github actions --- .github/workflows/cli.yml | 72 +++++++++++++++++++++++++++++++++++++++ .travis.yml | 55 ------------------------------ 2 files changed, 72 insertions(+), 55 deletions(-) create mode 100644 .github/workflows/cli.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml new file mode 100644 index 000000000..f97dfa743 --- /dev/null +++ b/.github/workflows/cli.yml @@ -0,0 +1,72 @@ +name: CLI + +on: + push: + branches: [develop] + pull_request: + branches: [develop] + +jobs: + build: + name: Build ${{ matrix.os }} + runs-on: ubuntu-latest + strategy: + matrix: + os: [linux, darwin, windows] + steps: + - name: Install dependencies + run: sudo apt-get update && sudo apt-get install git -y + - name: Set up Go 1.13 + uses: actions/setup-go@v2 + with: + go-version: 1.13 + id: go + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + - uses: actions/cache@v2 + with: + path: ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go- + - name: Build + run: GOOS=${{ matrix.os }} go build -o sops-${{ matrix.os }}-${{ github.sha }} -v go.mozilla.org/sops/cmd/sops + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: sops-${{ matrix.os }}-${{ github.sha }} + path: sops-${{ matrix.os }}-${{ github.sha }} + test: + name: Test + runs-on: ubuntu-latest + needs: [build] + env: + VAULT_VERSION: "1.1.3" + VAULT_TOKEN: "root" + VAULT_ADDR: "http://127.0.0.1:8200" + steps: + - name: rust-toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: "1.47.0" + override: true + - name: Check out code + uses: actions/checkout@v2 + - uses: actions/download-artifact@v2 + with: + name: sops-linux-${{ github.sha }} + - name: Move SOPS binary + run: mv sops-linux-${{ github.sha }} ./functional-tests/sops + - name: Make SOPS binary executable + run: chmod +x ./functional-tests/sops + - name: Download Vault + run: curl -O "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip" && sudo unzip vault_${VAULT_VERSION}_linux_amd64.zip -d /usr/local/bin/ + - name: Start Vault server + run: vault server -dev -dev-root-token-id="$VAULT_TOKEN" & + - name: Enable Vault KV + run: vault secrets enable -version=1 kv + - name: Import test GPG keys + run: for i in 1 2 3 4 5; do gpg --import pgp/sops_functional_tests_key.asc && break || sleep 15; done + - name: Run tests + run: cargo test + working-directory: ./functional-tests diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index dd5307efe..000000000 --- a/.travis.yml +++ /dev/null @@ -1,55 +0,0 @@ -language: go -go: 1.13 -go_import_path: go.mozilla.org/sops/ - -env: - - VAULT_VERSION=1.1.3 VAULT_TOKEN=root VAULT_ADDR='http://127.0.0.1:8200' - -addons: - apt: - packages: - - rpm - - ruby - - python3 - - unzip - -before_install: - - gem install fpm || sudo gem install fpm - - curl https://sh.rustup.rs -sSf | sh -s -- -y - - source ~/.cargo/env - - curl -O "https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip" && sudo unzip vault_${VAULT_VERSION}_linux_amd64.zip -d /usr/local/bin/ - -before_script: - - vault server -dev -dev-root-token-id="$VAULT_TOKEN" & - - sleep 5 - - vault secrets enable -version=1 kv - -script: - - '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: - - mkdir dist - - make deb-pkg rpm-pkg - - mv *.deb *.rpm dist/ - - GOOS=darwin CGO_ENABLED=0 GO111MODULE=on go build -mod vendor -o dist/sops-${TRAVIS_TAG}.darwin go.mozilla.org/sops/v3/cmd/sops - - GOOS=windows CGO_ENABLED=0 GO111MODULE=on go build -mod vendor -o dist/sops-${TRAVIS_TAG}.exe go.mozilla.org/sops/v3/cmd/sops - - GOOS=linux CGO_ENABLED=0 GO111MODULE=on go build -mod vendor -o dist/sops-${TRAVIS_TAG}.linux go.mozilla.org/sops/v3/cmd/sops - - | - if [ ! -z "$TRAVIS_TAG" ]; then - version="v$(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 - fi - fi - -deploy: - provider: releases - api_key: "${GITHUB_OAUTH_TOKEN}" - file_glob: true - file: dist/* - skip_cleanup: true - on: - tags: true From 88b05654b2c66a6d1f2c82533397513d80ff0625 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Tue, 29 Dec 2020 20:33:46 +0100 Subject: [PATCH 25/40] Remove dead code that fails compiling (#774). --- stores/ini/store.go | 50 --------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/stores/ini/store.go b/stores/ini/store.go index fce92597a..a701efca1 100644 --- a/stores/ini/store.go +++ b/stores/ini/store.go @@ -252,56 +252,6 @@ func (store *Store) encodeMetadataToIniBranch(md stores.Metadata) (sops.TreeBran return branch, nil } -func encodeMetadataItem(prefix string, kind reflect.Kind, field reflect.Value) (map[string]interface{}, error) { - - result := make(map[string]interface{}, 0) - - switch kind { - case reflect.Slice: - slf := field - for j := 0; j < slf.Len(); j++ { - item := slf.Index(j) - p := fmt.Sprintf("%s[%d]", prefix, j) - r, err := encodeMetadataItem(p, item.Type().Kind(), item) - if err != nil { - return result, err - } - for k, v := range r { - result[k] = v - } - } - case reflect.Struct: - for i := 0; i < field.NumField(); i++ { - sf := field.Type().Field(i) - var name string - if prefix == "" { - name = sf.Name - } else { - name = fmt.Sprintf("%s.%s", prefix, sf.Name) - } - r, err := encodeMetadataItem(name, sf.Type.Kind(), field.Field(i)) - if err != nil { - return result, err - } - for k, v := range r { - result[k] = v - } - } - case reflect.Int: - if field.Int() != 0 { - result[prefix] = string(field.Int()) - } - case reflect.String: - if field.String() != "" { - result[prefix] = strings.Replace(field.String(), "\n", "\\n", -1) - } - default: - return result, fmt.Errorf("Cannot encode %s, unexpected type %s", prefix, kind) - } - - return result, nil -} - // EmitPlainFile returns the plaintext INI file bytes corresponding to a sops.TreeBranches object func (store *Store) EmitPlainFile(in sops.TreeBranches) ([]byte, error) { out, err := store.iniFromTreeBranches(in) From 47cf265067d569de36f49b17ee2eae80ff16a3fb Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 30 Dec 2020 09:22:29 +0100 Subject: [PATCH 26/40] Forgot to remove no longer used import. --- stores/ini/store.go | 1 - 1 file changed, 1 deletion(-) diff --git a/stores/ini/store.go b/stores/ini/store.go index a701efca1..df5405294 100644 --- a/stores/ini/store.go +++ b/stores/ini/store.go @@ -5,7 +5,6 @@ import ( "encoding/json" "fmt" - "reflect" "strconv" "strings" From 157e633c14354e1d6fb7de1fe79d247ceafb3816 Mon Sep 17 00:00:00 2001 From: Adrian Utrilla Date: Wed, 6 Jan 2021 18:14:39 +0100 Subject: [PATCH 27/40] Use rustup directly instead of actions-rs --- .github/workflows/cli.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index f97dfa743..69e616f11 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -45,11 +45,8 @@ jobs: VAULT_TOKEN: "root" VAULT_ADDR: "http://127.0.0.1:8200" steps: - - name: rust-toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: "1.47.0" - override: true + - name: Install rustup + run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y --default-toolchain 1.47.0 - name: Check out code uses: actions/checkout@v2 - uses: actions/download-artifact@v2 From a115ce479f7d3e05a10ce2cedb6e59c2a5a17efd Mon Sep 17 00:00:00 2001 From: Adrian Utrilla Date: Thu, 7 Jan 2021 01:44:19 +0100 Subject: [PATCH 28/40] Also run unit tests in Github actions --- .github/workflows/cli.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 69e616f11..c1da5ab31 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -8,11 +8,15 @@ on: jobs: build: - name: Build ${{ matrix.os }} + name: Build and test ${{ matrix.os }} runs-on: ubuntu-latest strategy: matrix: os: [linux, darwin, windows] + env: + VAULT_VERSION: "1.1.3" + VAULT_TOKEN: "root" + VAULT_ADDR: "http://127.0.0.1:8200" steps: - name: Install dependencies run: sudo apt-get update && sudo apt-get install git -y @@ -31,13 +35,17 @@ jobs: ${{ runner.os }}-go- - name: Build run: GOOS=${{ matrix.os }} go build -o sops-${{ matrix.os }}-${{ github.sha }} -v go.mozilla.org/sops/cmd/sops + - name: Import test GPG keys + run: for i in 1 2 3 4 5; do gpg --import pgp/sops_functional_tests_key.asc && break || sleep 15; done + - name: Test + run: make test - name: Upload artifact uses: actions/upload-artifact@v2 with: name: sops-${{ matrix.os }}-${{ github.sha }} path: sops-${{ matrix.os }}-${{ github.sha }} test: - name: Test + name: Functional tests runs-on: ubuntu-latest needs: [build] env: From 49c2514d5c246229c20729513830176911359369 Mon Sep 17 00:00:00 2001 From: Christian Groschupp Date: Tue, 9 Feb 2021 13:11:32 +0100 Subject: [PATCH 29/40] add filename to exec-file (#761) * add filename to exec-file * update README.rst Co-authored-by: Christian Groschupp --- README.rst | 3 +++ cmd/sops/main.go | 10 ++++++++++ cmd/sops/subcommand/exec/exec.go | 9 +++++---- cmd/sops/subcommand/exec/exec_unix.go | 4 ++-- cmd/sops/subcommand/exec/exec_windows.go | 2 +- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 087aea07a..4c4ed0eec 100644 --- a/README.rst +++ b/README.rst @@ -1013,6 +1013,9 @@ encrypted file is only readable by root, but the target program does not need root privileges to function. This flag should be used where possible for added security. +To overwrite the default file name (``tmp-file``) in ``exec-file`` use the +``--filename `` parameter. + .. code:: bash # the encrypted file can't be read by the current user diff --git a/cmd/sops/main.go b/cmd/sops/main.go index 11a2ddfc6..148daa729 100644 --- a/cmd/sops/main.go +++ b/cmd/sops/main.go @@ -195,6 +195,10 @@ func main() { Name: "output-type", Usage: "currently json, yaml, dotenv and binary are supported. If not set, sops will use the input file's extension to determine the output format", }, + cli.StringFlag{ + Name: "filename", + Usage: "filename for the temporarily file (default: tmp-file)", + }, }, keyserviceFlags...), Action: func(c *cli.Context) error { if len(c.Args()) != 2 { @@ -222,12 +226,18 @@ func main() { return toExitError(err) } + filename := c.String("filename") + if filename == "" { + filename = "tmp-file" + } + if err := exec.ExecWithFile(exec.ExecOpts{ Command: command, Plaintext: output, Background: c.Bool("background"), Fifo: !c.Bool("no-fifo"), User: c.String("user"), + Filename: filename, }); err != nil { return toExitError(err) } diff --git a/cmd/sops/subcommand/exec/exec.go b/cmd/sops/subcommand/exec/exec.go index 95f135d79..cd8d33be5 100644 --- a/cmd/sops/subcommand/exec/exec.go +++ b/cmd/sops/subcommand/exec/exec.go @@ -24,10 +24,11 @@ type ExecOpts struct { Background bool Fifo bool User string + Filename string } -func GetFile(dir string) *os.File { - handle, err := ioutil.TempFile(dir, "tmp-file") +func GetFile(dir, filename string) *os.File { + handle, err := ioutil.TempFile(dir, filename) if err != nil { log.Fatal(err) } @@ -54,10 +55,10 @@ func ExecWithFile(opts ExecOpts) error { if opts.Fifo { // fifo handling needs to be async, even opening to write // will block if there is no reader present - filename = GetPipe(dir) + filename = GetPipe(dir, opts.Filename) go WritePipe(filename, opts.Plaintext) } else { - handle := GetFile(dir) + handle := GetFile(dir, opts.Filename) handle.Write(opts.Plaintext) handle.Close() filename = handle.Name() diff --git a/cmd/sops/subcommand/exec/exec_unix.go b/cmd/sops/subcommand/exec/exec_unix.go index f2041b7fb..cc831e798 100644 --- a/cmd/sops/subcommand/exec/exec_unix.go +++ b/cmd/sops/subcommand/exec/exec_unix.go @@ -27,8 +27,8 @@ func WritePipe(pipe string, contents []byte) { handle.Close() } -func GetPipe(dir string) string { - tmpfn := filepath.Join(dir, "tmp-file") +func GetPipe(dir, filename string) string { + tmpfn := filepath.Join(dir, filename) err := syscall.Mkfifo(tmpfn, 0600) if err != nil { log.Fatal(err) diff --git a/cmd/sops/subcommand/exec/exec_windows.go b/cmd/sops/subcommand/exec/exec_windows.go index 0c3345384..7e0f21d74 100644 --- a/cmd/sops/subcommand/exec/exec_windows.go +++ b/cmd/sops/subcommand/exec/exec_windows.go @@ -12,7 +12,7 @@ func WritePipe(pipe string, contents []byte) { log.Fatal("fifos are not available on windows") } -func GetPipe(dir string) string { +func GetPipe(dir, filename string) string { log.Fatal("fifos are not available on windows") return "" } From 0f2ebcf7ff9e866be0fa93d4242f0c2383994f89 Mon Sep 17 00:00:00 2001 From: Mikhail Katychev Date: Wed, 17 Feb 2021 21:21:20 +0000 Subject: [PATCH 30/40] added wrap verb to outputs (#817) --- age/keysource.go | 12 ++++++------ azkv/keysource.go | 4 ++-- decrypt/decrypt.go | 2 +- gcpkms/keysource.go | 8 ++++---- hcvault/keysource.go | 4 ++-- hcvault/keysource_test.go | 2 +- kms/keysource.go | 14 +++++++------- pgp/keysource_test.go | 4 ++-- shamir/shamir.go | 2 +- sops.go | 2 +- version/version.go | 2 +- 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index 48dff56d1..cd735721e 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -48,17 +48,17 @@ func (key *MasterKey) Encrypt(datakey []byte) error { w, err := age.Encrypt(buffer, key.parsedRecipient) if err != nil { - return fmt.Errorf("failed to open file for encrypting sops data key with age: %v", err) + return fmt.Errorf("failed to open file for encrypting sops data key with age: %w", err) } if _, err := w.Write(datakey); err != nil { log.WithField("recipient", key.parsedRecipient).Error("Encryption failed") - return fmt.Errorf("failed to encrypt sops data key with age: %v", err) + return fmt.Errorf("failed to encrypt sops data key with age: %w", err) } if err := w.Close(); err != nil { log.WithField("recipient", key.parsedRecipient).Error("Encryption failed") - return fmt.Errorf("failed to close file for encrypting sops data key with age: %v", err) + return fmt.Errorf("failed to close file for encrypting sops data key with age: %w", err) } key.EncryptedKey = buffer.String() @@ -95,7 +95,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { userConfigDir, err := os.UserConfigDir() if err != nil { - return nil, fmt.Errorf("user config directory could not be determined: %v", err) + return nil, fmt.Errorf("user config directory could not be determined: %w", err) } ageKeyFilePath = filepath.Join(userConfigDir, "sops", "age", "keys.txt") @@ -104,7 +104,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { ageKeyFile, err := os.Open(ageKeyFilePath) if err != nil { - return nil, fmt.Errorf("failed to open file: %v", err) + return nil, fmt.Errorf("failed to open file: %w", err) } defer ageKeyFile.Close() @@ -188,7 +188,7 @@ func parseRecipient(recipient string) (*age.X25519Recipient, error) { parsedRecipient, err := age.ParseX25519Recipient(recipient) if err != nil { - return nil, fmt.Errorf("failed to parse input as Bech32-encoded age public key: %v", err) + return nil, fmt.Errorf("failed to parse input as Bech32-encoded age public key: %w", err) } return parsedRecipient, nil diff --git a/azkv/keysource.go b/azkv/keysource.go index 85a549b7f..127ccccf8 100644 --- a/azkv/keysource.go +++ b/azkv/keysource.go @@ -210,7 +210,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { "key": key.Name, "version": key.Version, }).Error("Encryption failed") - return fmt.Errorf("Failed to encrypt data: %v", err) + return fmt.Errorf("Failed to encrypt data: %w", err) } key.EncryptedKey = *res.Result @@ -244,7 +244,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { "key": key.Name, "version": key.Version, }).Error("Decryption failed") - return nil, fmt.Errorf("Error decrypting key: %v", err) + return nil, fmt.Errorf("Error decrypting key: %w", err) } plaintext, err := base64.RawURLEncoding.DecodeString(*res.Result) diff --git a/decrypt/decrypt.go b/decrypt/decrypt.go index 5714fc17f..6fd4a4fbe 100644 --- a/decrypt/decrypt.go +++ b/decrypt/decrypt.go @@ -20,7 +20,7 @@ func File(path, format string) (cleartext []byte, err error) { // Read the file into an []byte encryptedData, err := ioutil.ReadFile(path) if err != nil { - return nil, fmt.Errorf("Failed to read %q: %v", path, err) + return nil, fmt.Errorf("Failed to read %q: %w", path, err) } // uses same logic as cli. diff --git a/gcpkms/keysource.go b/gcpkms/keysource.go index 8fd89af37..eee55433d 100644 --- a/gcpkms/keysource.go +++ b/gcpkms/keysource.go @@ -44,7 +44,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { cloudkmsService, err := key.createCloudKMSService() if err != nil { log.WithField("resourceID", key.ResourceID).Info("Encryption failed") - return fmt.Errorf("Cannot create GCP KMS service: %v", err) + return fmt.Errorf("Cannot create GCP KMS service: %w", err) } req := &cloudkms.EncryptRequest{ Plaintext: base64.StdEncoding.EncodeToString(dataKey), @@ -52,7 +52,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { resp, err := cloudkmsService.Projects.Locations.KeyRings.CryptoKeys.Encrypt(key.ResourceID, req).Do() if err != nil { log.WithField("resourceID", key.ResourceID).Info("Encryption failed") - return fmt.Errorf("Failed to call GCP KMS encryption service: %v", err) + return fmt.Errorf("Failed to call GCP KMS encryption service: %w", err) } log.WithField("resourceID", key.ResourceID).Info("Encryption succeeded") key.EncryptedKey = resp.Ciphertext @@ -72,7 +72,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { cloudkmsService, err := key.createCloudKMSService() if err != nil { log.WithField("resourceID", key.ResourceID).Info("Decryption failed") - return nil, fmt.Errorf("Cannot create GCP KMS service: %v", err) + return nil, fmt.Errorf("Cannot create GCP KMS service: %w", err) } req := &cloudkms.DecryptRequest{ @@ -81,7 +81,7 @@ func (key *MasterKey) Decrypt() ([]byte, error) { resp, err := cloudkmsService.Projects.Locations.KeyRings.CryptoKeys.Decrypt(key.ResourceID, req).Do() if err != nil { log.WithField("resourceID", key.ResourceID).Info("Decryption failed") - return nil, fmt.Errorf("Error decrypting key: %v", err) + return nil, fmt.Errorf("Error decrypting key: %w", err) } encryptedKey, err := base64.StdEncoding.DecodeString(resp.Plaintext) if err != nil { diff --git a/hcvault/keysource.go b/hcvault/keysource.go index 4d436f0dd..5078df619 100644 --- a/hcvault/keysource.go +++ b/hcvault/keysource.go @@ -123,7 +123,7 @@ func vaultClient(address string) (*api.Client, error) { cfg.Address = address cli, err := api.NewClient(cfg) if err != nil { - return nil, fmt.Errorf("Cannot create Vault Client: %v", err) + return nil, fmt.Errorf("Cannot create Vault Client: %w", err) } if cli.Token() != "" { return cli, nil @@ -239,7 +239,7 @@ func (key *MasterKey) createVaultTransitAndKey() error { return err } if err != nil { - return fmt.Errorf("Cannot create Vault Client: %v", err) + return fmt.Errorf("Cannot create Vault Client: %w", err) } err = cli.Sys().Mount(key.EnginePath, &api.MountInput{ Type: "transit", diff --git a/hcvault/keysource_test.go b/hcvault/keysource_test.go index f8682af66..9290acc1a 100644 --- a/hcvault/keysource_test.go +++ b/hcvault/keysource_test.go @@ -31,7 +31,7 @@ func TestMain(m *testing.M) { if err := pool.Retry(func() error { cli, err := api.NewClient(api.DefaultConfig()) if err != nil { - return fmt.Errorf("Cannot create Vault Client: %v", err) + return fmt.Errorf("Cannot create Vault Client: %w", err) } status, err := cli.Sys().InitStatus() if err != nil { diff --git a/kms/keysource.go b/kms/keysource.go index 9fa8172e8..a602aac25 100644 --- a/kms/keysource.go +++ b/kms/keysource.go @@ -63,14 +63,14 @@ func (key *MasterKey) Encrypt(dataKey []byte) error { sess, err := key.createSession() if err != nil { log.WithField("arn", key.Arn).Info("Encryption failed") - return fmt.Errorf("Failed to create session: %v", err) + return fmt.Errorf("Failed to create session: %w", err) } kmsSvc = kms.New(sess) } out, err := kmsSvc.Encrypt(&kms.EncryptInput{Plaintext: dataKey, KeyId: &key.Arn, EncryptionContext: key.EncryptionContext}) if err != nil { log.WithField("arn", key.Arn).Info("Encryption failed") - return fmt.Errorf("Failed to call KMS encryption service: %v", err) + return fmt.Errorf("Failed to call KMS encryption service: %w", err) } key.EncryptedKey = base64.StdEncoding.EncodeToString(out.CiphertextBlob) log.WithField("arn", key.Arn).Info("Encryption succeeded") @@ -98,14 +98,14 @@ func (key *MasterKey) Decrypt() ([]byte, error) { sess, err := key.createSession() if err != nil { log.WithField("arn", key.Arn).Info("Decryption failed") - return nil, fmt.Errorf("Error creating AWS session: %v", err) + return nil, fmt.Errorf("Error creating AWS session: %w", err) } kmsSvc = kms.New(sess) } decrypted, err := kmsSvc.Decrypt(&kms.DecryptInput{CiphertextBlob: k, EncryptionContext: key.EncryptionContext}) if err != nil { log.WithField("arn", key.Arn).Info("Decryption failed") - return nil, fmt.Errorf("Error decrypting key: %v", err) + return nil, fmt.Errorf("Error decrypting key: %w", err) } log.WithField("arn", key.Arn).Info("Decryption succeeded") return decrypted.Plaintext, nil @@ -167,7 +167,7 @@ func (key MasterKey) createStsSession(config aws.Config, sess *session.Session) } stsRoleSessionNameRe, err := regexp.Compile("[^a-zA-Z0-9=,.@-]+") if err != nil { - return nil, fmt.Errorf("Failed to compile STS role session name regex: %v", err) + return nil, fmt.Errorf("Failed to compile STS role session name regex: %w", err) } sanitizedHostname := stsRoleSessionNameRe.ReplaceAllString(hostname, "") stsService := sts.New(sess) @@ -175,13 +175,13 @@ func (key MasterKey) createStsSession(config aws.Config, sess *session.Session) out, err := stsService.AssumeRole(&sts.AssumeRoleInput{ RoleArn: &key.Role, RoleSessionName: &name}) if err != nil { - return nil, fmt.Errorf("Failed to assume role %q: %v", key.Role, err) + return nil, fmt.Errorf("Failed to assume role %q: %w", key.Role, err) } config.Credentials = credentials.NewStaticCredentials(*out.Credentials.AccessKeyId, *out.Credentials.SecretAccessKey, *out.Credentials.SessionToken) sess, err = session.NewSession(&config) if err != nil { - return nil, fmt.Errorf("Failed to create new aws session: %v", err) + return nil, fmt.Errorf("Failed to create new aws session: %w", err) } return sess, nil } diff --git a/pgp/keysource_test.go b/pgp/keysource_test.go index ff9abb7fd..0c10996d1 100644 --- a/pgp/keysource_test.go +++ b/pgp/keysource_test.go @@ -15,12 +15,12 @@ func TestPGP(t *testing.T) { return true } if err := key.Encrypt(x); err != nil { - t.Errorf("Failed to encrypt: %#v err: %v", x, err) + t.Errorf("Failed to encrypt: %#v err: %w", x, err) return false } k, err := key.Decrypt() if err != nil { - t.Errorf("Failed to decrypt: %#v err: %v", x, err) + t.Errorf("Failed to decrypt: %#v err: %w", x, err) return false } return bytes.Equal(x, k) diff --git a/shamir/shamir.go b/shamir/shamir.go index e44da6120..10d7bc3ba 100644 --- a/shamir/shamir.go +++ b/shamir/shamir.go @@ -215,7 +215,7 @@ func Split(secret []byte, parts, threshold int) ([][]byte, error) { // This polynomial crosses the y axis at `val`. p, err := makePolynomial(val, uint8(threshold-1)) if err != nil { - return nil, fmt.Errorf("failed to generate polynomial: %v", err) + return nil, fmt.Errorf("failed to generate polynomial: %w", err) } // Generate a `parts` number of (x,y) pairs diff --git a/sops.go b/sops.go index a41f4a2d1..a6caa0df8 100644 --- a/sops.go +++ b/sops.go @@ -596,7 +596,7 @@ func (m *Metadata) UpdateMasterKeysWithKeyServices(dataKey []byte, svcs []keyser Plaintext: part, }) if err != nil { - keyErrs = append(keyErrs, fmt.Errorf("failed to encrypt new data key with master key %q: %v", key.ToString(), err)) + keyErrs = append(keyErrs, fmt.Errorf("failed to encrypt new data key with master key %q: %w", key.ToString(), err)) continue } key.SetEncryptedDataKey(rsp.Ciphertext) diff --git a/version/version.go b/version/version.go index 892ff6f59..4093f7363 100644 --- a/version/version.go +++ b/version/version.go @@ -74,7 +74,7 @@ func RetrieveLatestVersionFromUpstream() (string, error) { // try to parse the version as semver _, err := semver.Make(comps[1]) if err != nil { - return "", fmt.Errorf("Retrieved version %q does not match semver format: %v", comps[1], err) + return "", fmt.Errorf("Retrieved version %q does not match semver format: %w", comps[1], err) } return comps[1], nil } From 5d1376d56d2ebb2df7588069ffc45d6bbf95ba1b Mon Sep 17 00:00:00 2001 From: Andreas <704542+tullo@users.noreply.github.com> Date: Sun, 21 Feb 2021 09:06:40 +0100 Subject: [PATCH 31/40] Use age/armor for encrypted data key (#819) * Use age/armor for encrypted data key Currently the encrypted data key is stored as a binary value, and this results in SOPS encrypted DOTENV files having weird binary characters. This changes the encrypt/decrypt methods to use the armor reader writer provided by: filippo.io/age/armor Signed-off-by: Andreas Amstutz * upgrade filippo.io/age to v1.0.0-beta7 Signed-off-by: Andreas Amstutz * add unit test Signed-off-by: Andreas Amstutz Co-authored-by: Andreas Amstutz --- age/keysource.go | 22 +++++++++++++++------- age/keysource_test.go | 28 +++++++++++++++++++++++++++- go.mod | 5 +++-- go.sum | 37 ++++++++++--------------------------- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/age/keysource.go b/age/keysource.go index cd735721e..c0b9c6561 100644 --- a/age/keysource.go +++ b/age/keysource.go @@ -9,6 +9,7 @@ import ( "strings" "filippo.io/age" + "filippo.io/age/armor" "github.com/sirupsen/logrus" "go.mozilla.org/sops/v3/logging" ) @@ -46,7 +47,8 @@ func (key *MasterKey) Encrypt(datakey []byte) error { key.parsedRecipient = parsedRecipient } - w, err := age.Encrypt(buffer, key.parsedRecipient) + aw := armor.NewWriter(buffer) + w, err := age.Encrypt(aw, key.parsedRecipient) if err != nil { return fmt.Errorf("failed to open file for encrypting sops data key with age: %w", err) } @@ -61,6 +63,11 @@ func (key *MasterKey) Encrypt(datakey []byte) error { return fmt.Errorf("failed to close file for encrypting sops data key with age: %w", err) } + if err := aw.Close(); err != nil { + log.WithField("recipient", key.parsedRecipient).Error("Encryption failed") + return fmt.Errorf("failed to close armored writer: %w", err) + } + key.EncryptedKey = buffer.String() log.WithField("recipient", key.parsedRecipient).Info("Encryption succeeded") @@ -115,19 +122,20 @@ func (key *MasterKey) Decrypt() ([]byte, error) { return nil, err } - buffer := &bytes.Buffer{} - reader := bytes.NewReader([]byte(key.EncryptedKey)) - r, err := age.Decrypt(reader, identities...) + src := bytes.NewReader([]byte(key.EncryptedKey)) + ar := armor.NewReader(src) + r, err := age.Decrypt(ar, identities...) if err != nil { return nil, fmt.Errorf("no age identity found in %q that could decrypt the data", ageKeyFilePath) } - if _, err := io.Copy(buffer, r); err != nil { - return nil, fmt.Errorf("failed to copy decrypted data into bytes.Buffer") + var b bytes.Buffer + if _, err := io.Copy(&b, r); err != nil { + return nil, fmt.Errorf("failed to copy decrypted data into bytes.Buffer: %w", err) } - return buffer.Bytes(), nil + return b.Bytes(), nil } // NeedsRotation returns whether the data key needs to be rotated or not. diff --git a/age/keysource_test.go b/age/keysource_test.go index 51fc91519..2a3bebdfd 100644 --- a/age/keysource_test.go +++ b/age/keysource_test.go @@ -17,7 +17,7 @@ func TestMasterKeysFromRecipientsEmpty(t *testing.T) { assert.NoError(err) - assert.Equal(recipients, make([]*MasterKey,0)) + assert.Equal(recipients, make([]*MasterKey, 0)) } func TestAge(t *testing.T) { @@ -41,3 +41,29 @@ func TestAge(t *testing.T) { assert.NoError(err) assert.Equal(dataKey, decryptedKey) } + +func TestAgeDotEnv(t *testing.T) { + assert := assert.New(t) + + key, err := MasterKeyFromRecipient("age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw") + + assert.NoError(err) + assert.Equal("age1yt3tfqlfrwdwx0z0ynwplcr6qxcxfaqycuprpmy89nr83ltx74tqdpszlw", key.ToString()) + + dotenv := `IMAGE_PREFIX=repo/service- +APPLICATION_KEY=K6pfAWuUVND9Fz5SC7jmA6pfAWuUVND9Fz5SC7jmA +KEY_ID=003683d721f2ae683d721f2a1 +DOMAIN=files.127.0.0.1.nip.io` + dataKey := []byte(dotenv) + + err = key.Encrypt(dataKey) + assert.NoError(err) + + _, filename, _, _ := runtime.Caller(0) + err = os.Setenv("SOPS_AGE_KEY_FILE", path.Join(path.Dir(filename), "keys.txt")) + assert.NoError(err) + + decryptedKey, err := key.Decrypt() + assert.NoError(err) + assert.Equal(dataKey, decryptedKey) +} diff --git a/go.mod b/go.mod index 849557af5..934d0e6a4 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.13 require ( cloud.google.com/go v0.43.0 - filippo.io/age v1.0.0-beta5 + filippo.io/age v1.0.0-beta7 github.com/Azure/azure-sdk-for-go v31.2.0+incompatible github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Azure/go-autorest/autorest v0.9.0 @@ -40,9 +40,10 @@ require ( github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 // indirect github.com/stretchr/testify v1.5.1 go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a - golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 + golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 + golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 // indirect google.golang.org/api v0.7.0 google.golang.org/grpc v1.27.0 google.golang.org/protobuf v1.25.0 diff --git a/go.sum b/go.sum index e017155d8..bf2cfb87a 100644 --- a/go.sum +++ b/go.sum @@ -3,10 +3,10 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.43.0 h1:banaiRPAM8kUVYneOSkhgcDsLzEvL25FinuiSZaH/2w= cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= -contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= -filippo.io/age v1.0.0-beta5 h1:H3R+VF81f69NdAQhBOSviEtgUd1cZRS1URhUlm2oXjw= -filippo.io/age v1.0.0-beta5/go.mod h1:TOa3exZvzRCLfjmbJGsqwSQ0HtWjJfTTCQnQsNCC4E0= +filippo.io/age v1.0.0-beta7 h1:RZiSK+N3KL2UwT82xiCavjYw8jJHzWMEUYePAukTpk0= +filippo.io/age v1.0.0-beta7/go.mod h1:chAuTrTb0FTTmKtvs6fQTGhYTvH9AigjN1uEUsvLdZ0= +filippo.io/edwards25519 v1.0.0-alpha.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o= github.com/Azure/azure-sdk-for-go v31.2.0+incompatible h1:kZFnTLmdQYNGfakatSivKHUfUnDZhqNdchHD4oIhp5k= github.com/Azure/azure-sdk-for-go v31.2.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8= @@ -23,7 +23,6 @@ github.com/Azure/go-autorest/autorest/azure/cli v0.1.0 h1:YTtBrcb6mhA+PoSW8WxFDo github.com/Azure/go-autorest/autorest/azure/cli v0.1.0/go.mod h1:Dk8CUAt/b/PzkfeRsWzVG9Yj3ps8mS8ECztu43rdU8U= github.com/Azure/go-autorest/autorest/date v0.1.0 h1:YGrhWfrgtFs84+h0o46rJrlmsZtyZRg470CqAXTZaGM= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/mocks v0.1.0 h1:Kx+AUU2Te+A3JIyYn6Dfs+cFgx5XorQKuIXrZGoq/SI= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0 h1:Ww5g4zThfD/6cLb4z6xxgeyDa7QDkizMkJKe0ysZXp0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= @@ -33,7 +32,6 @@ github.com/Azure/go-autorest/autorest/validation v0.2.0 h1:15vMO4y76dehZSq7pAaOL github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.1.0 h1:TRBxC5Pj/fIuh4Qob0ZpkggbfT8RC0SubHbpV3p4/Vc= github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= @@ -45,9 +43,7 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -60,7 +56,6 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -102,7 +97,6 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= @@ -117,7 +111,6 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -140,7 +133,6 @@ github.com/gotestyourself/gotestyourself v2.2.0+incompatible h1:AQwinXlbQR2HvPjQ github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/goware/prefixer v0.0.0-20160118172347-395022866408 h1:Y9iQJfEqnN3/Nce9cOegemcy/9Ai5k3huT6E80F3zaw= github.com/goware/prefixer v0.0.0-20160118172347-395022866408/go.mod h1:PE1ycukgRPJ7bJ9a1fdfQ9j8i/cEcRAoLZzbxYpNB/s= -github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -209,10 +201,6 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c h1:yE1NxRAZA3wF0laDWECtOe2J0tFjSHUI6MXXbMif+QY= -github.com/mozilla-services/yaml v0.0.0-20191106225358-5c216288813c/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= -github.com/mozilla-services/yaml v0.0.0-20201006214821-a130ed024dcf h1:Lcffxn0MTcVD0v/kBCul62VDj0st4zxBSahSf03hGEc= -github.com/mozilla-services/yaml v0.0.0-20201006214821-a130ed024dcf/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= github.com/mozilla-services/yaml v0.0.0-20201007153854-c369669a6625 h1:5IeGQzguDQ+EsTR5HE7tMYkZe09mqQ9cDypdKQEB5Kg= github.com/mozilla-services/yaml v0.0.0-20201007153854-c369669a6625/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -233,7 +221,6 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -245,7 +232,6 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -268,14 +254,12 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a h1:N7VD+PwpJME2ZfQT8+ejxwA4Ow10IkGbU0MGf94ll8k= go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a/go.mod h1:YDKUvO0b//78PaaEro6CAPH6NqohCmL2Cwju5XI2HoE= -go.mozilla.org/sops v0.0.0-20190912205235-14a22d7a7060 h1:KnOZgR0z89tCwGympfPkpzXdlCmhksUP5ddQ+Iqo1FU= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -285,8 +269,9 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59 h1:3zb4D3T4G8jdExgVU/95+vQXfpEPiMdCaZgmGVxjNHM= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -310,7 +295,6 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -322,7 +306,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -340,8 +323,12 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0 h1:HyfiK1WMnHj5FXFXatD+Qs1A/xC2Run6RzeW1SyHxpc= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 h1:SgQ6LNaYJU0JIuEHv9+s6EbhSCwYeAf5Yvj6lpYlqAE= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -380,7 +367,6 @@ google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610 h1:Ygq9/SRJX9+dU0WCIICM8RkWvDw03lvB77hrhJnpxfU= google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= @@ -404,11 +390,9 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -423,7 +407,6 @@ gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From 24636e4f231a1559305b5d9549b48d217dd3b4e1 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 21 Feb 2021 18:46:12 +0100 Subject: [PATCH 32/40] Make sure that binary is built from current checkout, and not from master branch. (#820) --- .github/workflows/cli.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index c1da5ab31..30ffde52f 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -34,7 +34,7 @@ jobs: restore-keys: | ${{ runner.os }}-go- - name: Build - run: GOOS=${{ matrix.os }} go build -o sops-${{ matrix.os }}-${{ github.sha }} -v go.mozilla.org/sops/cmd/sops + run: GOOS=${{ matrix.os }} go build -o sops-${{ matrix.os }}-${{ github.sha }} -v ./cmd/sops - name: Import test GPG keys run: for i in 1 2 3 4 5; do gpg --import pgp/sops_functional_tests_key.asc && break || sleep 15; done - name: Test From e2d6d0fdc30b7626f4a660dd7f21b2db583fae57 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Sun, 21 Feb 2021 18:48:23 +0100 Subject: [PATCH 33/40] Use yaml.v3 instead of modified yaml.v2 for handling YAML files (#791) * Add another test (that currently fails). * First shot at using yaml.v3 for reading YAML files with comments. * Allow parsing multi-document YAML files. * Use Decoder to parse multi-part documents. * Use yaml.v3 for config and audit. * First step of serializing YAML using yaml.v3. * Always serialize with yaml.v3. * Remove debug prints. * Remove traces of github.com/mozilla-services/yaml. * Improve serialization of documents consisting only of comments. * Improve handling of some empty documents. * Adjust to latest changes in go-yaml/yaml#684. * Bump yaml.v3 version, temporarily disable failing tests. * Run go mod tidy. * Fix CI. --- audit/audit.go | 2 +- config/config.go | 2 +- go.mod | 2 +- go.sum | 4 +- stores/yaml/store.go | 382 ++++++++++++++++++++++++++++---------- stores/yaml/store_test.go | 74 +++++++- 6 files changed, 361 insertions(+), 105 deletions(-) diff --git a/audit/audit.go b/audit/audit.go index 1a29f5ea2..b52215077 100644 --- a/audit/audit.go +++ b/audit/audit.go @@ -12,7 +12,7 @@ import ( // empty import as per https://godoc.org/github.com/lib/pq _ "github.com/lib/pq" - "github.com/mozilla-services/yaml" + "gopkg.in/yaml.v3" "github.com/sirupsen/logrus" "go.mozilla.org/sops/v3/logging" ) diff --git a/config/config.go b/config/config.go index 91f31df3c..18a71c3df 100644 --- a/config/config.go +++ b/config/config.go @@ -10,7 +10,7 @@ import ( "path" "regexp" - "github.com/mozilla-services/yaml" + "gopkg.in/yaml.v3" "github.com/sirupsen/logrus" "go.mozilla.org/sops/v3" "go.mozilla.org/sops/v3/age" diff --git a/go.mod b/go.mod index 934d0e6a4..4defa0447 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,6 @@ require ( github.com/lib/pq v1.2.0 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-wordwrap v1.0.0 - github.com/mozilla-services/yaml v0.0.0-20201007153854-c369669a6625 github.com/opencontainers/go-digest v1.0.0-rc1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/runc v0.1.1 // indirect @@ -49,5 +48,6 @@ require ( google.golang.org/protobuf v1.25.0 gopkg.in/ini.v1 v1.44.0 gopkg.in/urfave/cli.v1 v1.20.0 + gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc gotest.tools v2.2.0+incompatible // indirect ) diff --git a/go.sum b/go.sum index bf2cfb87a..dcc5988c2 100644 --- a/go.sum +++ b/go.sum @@ -201,8 +201,6 @@ github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUb github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mozilla-services/yaml v0.0.0-20201007153854-c369669a6625 h1:5IeGQzguDQ+EsTR5HE7tMYkZe09mqQ9cDypdKQEB5Kg= -github.com/mozilla-services/yaml v0.0.0-20201007153854-c369669a6625/go.mod h1:Is/Ucts/yU/mWyGR8yELRoO46mejouKsJfQLAIfTR18= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -410,6 +408,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc h1:XANm4xAMEQhRdWKqaL0qmhGDv7RuobwCO97TIlktaQE= +gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/stores/yaml/store.go b/stores/yaml/store.go index 989a4f056..a3ae2fb46 100644 --- a/stores/yaml/store.go +++ b/stores/yaml/store.go @@ -1,9 +1,12 @@ package yaml //import "go.mozilla.org/sops/v3/stores/yaml" import ( + "bytes" "fmt" + "io" + "strings" - "github.com/mozilla-services/yaml" + "gopkg.in/yaml.v3" "go.mozilla.org/sops/v3" "go.mozilla.org/sops/v3/stores" ) @@ -12,102 +15,232 @@ import ( type Store struct { } -func (store Store) mapSliceToTreeBranch(in yaml.MapSlice) sops.TreeBranch { - branch := make(sops.TreeBranch, 0) - for _, item := range in { - if comment, ok := item.Key.(yaml.Comment); ok { - // Convert the yaml comment to a generic sops comment - branch = append(branch, sops.TreeItem{ - Key: sops.Comment{ - Value: comment.Value, - }, - Value: nil, - }) - } else { - branch = append(branch, sops.TreeItem{ - Key: item.Key, - Value: store.yamlValueToTreeValue(item.Value), - }) +func (store Store) appendCommentToList(comment string, list []interface{}) []interface{} { + if comment != "" { + for _, commentLine := range strings.Split(comment, "\n") { + if commentLine != "" { + list = append(list, sops.Comment{ + Value: commentLine[1:], + }) + } + } + } + return list +} + +func (store Store) appendCommentToMap(comment string, branch sops.TreeBranch) sops.TreeBranch { + if comment != "" { + for _, commentLine := range strings.Split(comment, "\n") { + if commentLine != "" { + branch = append(branch, sops.TreeItem{ + Key: sops.Comment{ + Value: commentLine[1:], + }, + Value: nil, + }) + } } } return branch } -func (store Store) yamlValueToTreeValue(in interface{}) interface{} { - switch in := in.(type) { - case map[interface{}]interface{}: - return store.yamlMapToTreeBranch(in) - case yaml.MapSlice: - return store.mapSliceToTreeBranch(in) - case []interface{}: - return store.yamlSliceToTreeValue(in) - case yaml.Comment: - return sops.Comment{Value: in.Value} - default: - return in +func (store Store) nodeToTreeValue(node *yaml.Node, commentsWereHandled bool) (interface{}, error) { + switch node.Kind { + case yaml.DocumentNode: + panic("documents should never be passed here") + case yaml.SequenceNode: + var result []interface{} + if !commentsWereHandled { + result = store.appendCommentToList(node.HeadComment, result) + result = store.appendCommentToList(node.LineComment, result) + } + for _, item := range node.Content { + result = store.appendCommentToList(item.HeadComment, result) + result = store.appendCommentToList(item.LineComment, result) + val, err := store.nodeToTreeValue(item, true) + if err != nil { + return nil, err + } + result = append(result, val) + result = store.appendCommentToList(item.FootComment, result) + } + if !commentsWereHandled { + result = store.appendCommentToList(node.FootComment, result) + } + return result, nil + case yaml.MappingNode: + branch := make(sops.TreeBranch, 0) + return store.appendYamlNodeToTreeBranch(node, branch, false) + case yaml.ScalarNode: + var result interface{} + node.Decode(&result) + return result, nil + case yaml.AliasNode: + return store.nodeToTreeValue(node.Alias, false); } + return nil, nil } -func (store *Store) yamlSliceToTreeValue(in []interface{}) []interface{} { - for i, v := range in { - in[i] = store.yamlValueToTreeValue(v) +func (store Store) appendYamlNodeToTreeBranch(node *yaml.Node, branch sops.TreeBranch, commentsWereHandled bool) (sops.TreeBranch, error) { + var err error + if !commentsWereHandled { + branch = store.appendCommentToMap(node.HeadComment, branch) + branch = store.appendCommentToMap(node.LineComment, branch) + } + switch node.Kind { + case yaml.DocumentNode: + for _, item := range node.Content { + branch, err = store.appendYamlNodeToTreeBranch(item, branch, false) + if err != nil { + return nil, err + } + } + case yaml.SequenceNode: + return nil, fmt.Errorf("YAML documents that are sequences are not supported") + case yaml.MappingNode: + for i := 0; i < len(node.Content); i += 2 { + key := node.Content[i] + value := node.Content[i + 1] + branch = store.appendCommentToMap(key.HeadComment, branch) + branch = store.appendCommentToMap(key.LineComment, branch) + handleValueComments := value.Kind == yaml.ScalarNode || value.Kind == yaml.AliasNode + if handleValueComments { + branch = store.appendCommentToMap(value.HeadComment, branch) + branch = store.appendCommentToMap(value.LineComment, branch) + } + var keyValue interface{} + key.Decode(&keyValue) + valueTV, err := store.nodeToTreeValue(value, handleValueComments) + if err != nil { + return nil, err + } + branch = append(branch, sops.TreeItem{ + Key: keyValue, + Value: valueTV, + }) + if handleValueComments { + branch = store.appendCommentToMap(value.FootComment, branch) + } + branch = store.appendCommentToMap(key.FootComment, branch) + } + case yaml.ScalarNode: + // A empty document with a document start marker without comments results in null + if node.ShortTag() == "!!null" { + return branch, nil + } + return nil, fmt.Errorf("YAML documents that are values are not supported") + case yaml.AliasNode: + branch, err = store.appendYamlNodeToTreeBranch(node.Alias, branch, false) } - return in + if !commentsWereHandled { + branch = store.appendCommentToMap(node.FootComment, branch) + } + return branch, nil } -func (store *Store) yamlMapToTreeBranch(in map[interface{}]interface{}) sops.TreeBranch { +func (store Store) yamlDocumentNodeToTreeBranch(in yaml.Node) (sops.TreeBranch, error) { branch := make(sops.TreeBranch, 0) - for k, v := range in { - branch = append(branch, sops.TreeItem{ - Key: k.(string), - Value: store.yamlValueToTreeValue(v), - }) + return store.appendYamlNodeToTreeBranch(&in, branch, false) +} + +func (store *Store) addCommentsHead(node *yaml.Node, comments []string) []string { + if len(comments) > 0 { + comment := "#" + strings.Join(comments, "\n#") + if len(node.HeadComment) > 0 { + node.HeadComment = comment + "\n" + node.HeadComment + } else { + node.HeadComment = comment + } } - return branch + return nil } -func (store Store) treeValueToYamlValue(in interface{}) interface{} { +func (store *Store) addCommentsFoot(node *yaml.Node, comments []string) []string { + if len(comments) > 0 { + comment := "#" + strings.Join(comments, "\n#") + if len(node.FootComment) > 0 { + node.FootComment += "\n" + comment + } else { + node.FootComment = comment + } + } + return nil +} + +func (store *Store) treeValueToNode(in interface{}) *yaml.Node { switch in := in.(type) { case sops.TreeBranch: - return store.treeBranchToYamlMap(in) - case sops.Comment: - return yaml.Comment{in.Value} + var mapping = &yaml.Node{} + mapping.Kind = yaml.MappingNode + store.appendTreeBranch(in, mapping) + return mapping case []interface{}: - var out []interface{} - for _, v := range in { - out = append(out, store.treeValueToYamlValue(v)) - } - return out + var sequence = &yaml.Node{} + sequence.Kind = yaml.SequenceNode + store.appendSequence(in, sequence) + return sequence default: - return in + var valueNode = &yaml.Node{} + valueNode.Encode(in) + return valueNode } } -func (store Store) treeBranchToYamlMap(in sops.TreeBranch) yaml.MapSlice { - branch := make(yaml.MapSlice, 0) +func (store *Store) appendSequence(in []interface{}, sequence *yaml.Node) { + var comments []string + var beginning bool = true for _, item := range in { + if comment, ok := item.(sops.Comment); ok { + comments = append(comments, comment.Value) + } else { + if beginning { + comments = store.addCommentsHead(sequence, comments) + beginning = false + } + itemNode := store.treeValueToNode(item) + comments = store.addCommentsHead(itemNode, comments) + sequence.Content = append(sequence.Content, itemNode) + } + } + if len(comments) > 0 { + if beginning { + comments = store.addCommentsHead(sequence, comments) + } else { + comments = store.addCommentsFoot(sequence.Content[len(sequence.Content) - 1], comments) + } + } +} + +func (store *Store) appendTreeBranch(branch sops.TreeBranch, mapping *yaml.Node) { + var comments []string + var beginning bool = true + for _, item := range branch { if comment, ok := item.Key.(sops.Comment); ok { - branch = append(branch, yaml.MapItem{ - Key: store.treeValueToYamlValue(comment), - Value: nil, - }) + comments = append(comments, comment.Value) } else { - branch = append(branch, yaml.MapItem{ - Key: item.Key, - Value: store.treeValueToYamlValue(item.Value), - }) + if beginning { + comments = store.addCommentsHead(mapping, comments) + beginning = false + } + var keyNode = &yaml.Node{} + keyNode.Encode(item.Key) + comments = store.addCommentsHead(keyNode, comments) + valueNode := store.treeValueToNode(item.Value) + mapping.Content = append(mapping.Content, keyNode, valueNode) + } + } + if len(comments) > 0 { + if beginning { + comments = store.addCommentsHead(mapping, comments) + } else { + comments = store.addCommentsFoot(mapping.Content[len(mapping.Content) - 1], comments) } } - return branch } // LoadEncryptedFile loads the contents of an encrypted yaml file onto a // sops.Tree runtime object 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. @@ -123,14 +256,33 @@ func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) { if err != nil { return sops.Tree{}, err } + var data yaml.Node + if err := yaml.Unmarshal(in, &data); err != nil { + return sops.Tree{}, fmt.Errorf("Error unmarshaling input YAML: %s", err) + } 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:]...) + d := yaml.NewDecoder(bytes.NewReader(in)) + for true { + var data yaml.Node + err := d.Decode(&data) + if err == io.EOF { + break + } + if err != nil { + return sops.Tree{}, fmt.Errorf("Error unmarshaling input YAML: %s", err) + } + + branch, err := store.yamlDocumentNodeToTreeBranch(data) + if err != nil { + return sops.Tree{}, fmt.Errorf("Error unmarshaling input YAML: %s", err) + } + + for i, elt := range branch { + if elt.Key == "sops" { // Erase + branch = append(branch[:i], branch[i+1:]...) } } - branches = append(branches, store.mapSliceToTreeBranch(doc)) + branches = append(branches, branch) } return sops.Tree{ Branches: branches, @@ -139,16 +291,25 @@ func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) { } // LoadPlainFile loads the contents of a plaintext yaml file onto a -// sops.Tree runtime obejct +// sops.Tree runtime object 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) - } - var branches sops.TreeBranches - for _, doc := range data { - branches = append(branches, store.mapSliceToTreeBranch(doc)) + d := yaml.NewDecoder(bytes.NewReader(in)) + for true { + var data yaml.Node + err := d.Decode(&data) + if err == io.EOF { + break + } + if err != nil { + return nil, fmt.Errorf("Error unmarshaling input YAML: %s", err) + } + + branch, err := store.yamlDocumentNodeToTreeBranch(data) + if err != nil { + return nil, fmt.Errorf("Error unmarshaling input YAML: %s", err) + } + branches = append(branches, branch) } return branches, nil } @@ -156,45 +317,70 @@ func (store *Store) LoadPlainFile(in []byte) (sops.TreeBranches, error) { // EmitEncryptedFile returns the encrypted bytes of the yaml file corresponding to a // sops.Tree runtime object func (store *Store) EmitEncryptedFile(in sops.Tree) ([]byte, error) { - 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) + var b bytes.Buffer + e := yaml.NewEncoder(io.Writer(&b)) + e.SetIndent(4) + for _, branch := range in.Branches { + // Document root + var doc = yaml.Node{} + doc.Kind = yaml.DocumentNode + // Add global mapping + var mapping = yaml.Node{} + mapping.Kind = yaml.MappingNode + doc.Content = append(doc.Content, &mapping) + // Create copy of branch with metadata appended + branch = append(sops.TreeBranch(nil), branch...) + branch = append(branch, sops.TreeItem{ + Key: "sops", + Value: stores.MetadataFromInternal(in.Metadata), + }) + // Marshal branch to global mapping node + store.appendTreeBranch(branch, &mapping) + // Encode YAML + err := e.Encode(&doc) if err != nil { return nil, fmt.Errorf("Error marshaling to yaml: %s", err) } - out = append(out, tout...) } - return out, nil + e.Close() + return b.Bytes(), nil } // EmitPlainFile returns the plaintext bytes of the yaml file corresponding to a // sops.TreeBranches runtime object func (store *Store) EmitPlainFile(branches sops.TreeBranches) ([]byte, error) { - var out []byte - for i, branch := range branches { - if i > 0 { - out = append(out, "---\n"...) + var b bytes.Buffer + e := yaml.NewEncoder(io.Writer(&b)) + e.SetIndent(4) + for _, branch := range branches { + // Document root + var doc = yaml.Node{} + doc.Kind = yaml.DocumentNode + // Add global mapping + var mapping = yaml.Node{} + mapping.Kind = yaml.MappingNode + // Marshal branch to global mapping node + store.appendTreeBranch(branch, &mapping) + if len(mapping.Content) == 0 { + doc.HeadComment = mapping.HeadComment + } else { + doc.Content = append(doc.Content, &mapping) } - yamlMap := store.treeBranchToYamlMap(branch) - tmpout, err := (&yaml.YAMLMarshaler{Indent: 4}).Marshal(yamlMap) + // Encode YAML + err := e.Encode(&doc) if err != nil { return nil, fmt.Errorf("Error marshaling to yaml: %s", err) } - out = append(out[:], tmpout[:]...) } - return out, nil + e.Close() + return b.Bytes(), nil } // EmitValue returns bytes corresponding to a single encoded value // in a generic interface{} object func (store *Store) EmitValue(v interface{}) ([]byte, error) { - v = store.treeValueToYamlValue(v) - return (&yaml.YAMLMarshaler{Indent: 4}).Marshal(v) + n := store.treeValueToNode(v) + return yaml.Marshal(n) } // EmitExample returns the bytes corresponding to an example complex tree diff --git a/stores/yaml/store_test.go b/stores/yaml/store_test.go index d8ccc4c46..be6b90eb2 100644 --- a/stores/yaml/store_test.go +++ b/stores/yaml/store_test.go @@ -15,6 +15,12 @@ key1_a: value --- key2: value2`) +var PLAIN_0 = []byte(`# comment 0 +key1: value +key1_a: value +# ^ comment 1 +`) + var BRANCHES = sops.TreeBranches{ sops.TreeBranch{ sops.TreeItem{ @@ -73,8 +79,16 @@ prometheus-node-exporter: ## jobLabel: node-exporter extraArgs: - - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/) - - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$ + - --collector.filesystem.ignored-mount-points=^/(dev|proc|sys|var/lib/docker/.+)($|/) + - --collector.filesystem.ignored-fs-types=^(autofs|binfmt_misc|cgroup|configfs|debugfs|devpts|devtmpfs|fusectl|hugetlbfs|mqueue|overlay|proc|procfs|pstore|rpc_pipefs|securityfs|sysfs|tracefs)$ +`) + +var COMMENT_4 = []byte(`# foo +`) + +var COMMENT_5 = []byte(`# foo +--- +key: value `) func TestUnmarshalMetadataFromNonSOPSFile(t *testing.T) { @@ -95,6 +109,7 @@ func TestComment1(t *testing.T) { assert.Nil(t, err) bytes, err := (&Store{}).EmitPlainFile(branches) assert.Nil(t, err) + assert.Equal(t, string(COMMENT_1), string(bytes)) assert.Equal(t, COMMENT_1, bytes) } @@ -104,6 +119,7 @@ func TestComment2(t *testing.T) { assert.Nil(t, err) bytes, err := (&Store{}).EmitPlainFile(branches) assert.Nil(t, err) + assert.Equal(t, string(COMMENT_2), string(bytes)) assert.Equal(t, COMMENT_2, bytes) } @@ -113,5 +129,59 @@ func TestComment3(t *testing.T) { assert.Nil(t, err) bytes, err := (&Store{}).EmitPlainFile(branches) assert.Nil(t, err) + assert.Equal(t, string(COMMENT_3_OUT), string(bytes)) assert.Equal(t, COMMENT_3_OUT, bytes) } + +/* TODO: re-enable once https://github.com/go-yaml/yaml/pull/690 is merged +func TestComment4(t *testing.T) { + // First iteration: load and store + branches, err := (&Store{}).LoadPlainFile(COMMENT_4) + assert.Nil(t, err) + bytes, err := (&Store{}).EmitPlainFile(branches) + assert.Nil(t, err) + assert.Equal(t, string(COMMENT_4), string(bytes)) + assert.Equal(t, COMMENT_4, bytes) +} + +func TestComment5(t *testing.T) { + // First iteration: load and store + branches, err := (&Store{}).LoadPlainFile(COMMENT_5) + assert.Nil(t, err) + bytes, err := (&Store{}).EmitPlainFile(branches) + assert.Nil(t, err) + assert.Equal(t, string(COMMENT_5), string(bytes)) + assert.Equal(t, COMMENT_5, bytes) +} +*/ + +func TestEmpty(t *testing.T) { + // First iteration: load and store + branches, err := (&Store{}).LoadPlainFile([]byte(``)) + assert.Nil(t, err) + assert.Equal(t, len(branches), 0) + bytes, err := (&Store{}).EmitPlainFile(branches) + assert.Nil(t, err) + assert.Equal(t, ``, string(bytes)) +} + +/* TODO: re-enable once https://github.com/go-yaml/yaml/pull/690 is merged +func TestEmpty2(t *testing.T) { + // First iteration: load and store + branches, err := (&Store{}).LoadPlainFile([]byte(`---`)) + assert.Nil(t, err) + assert.Equal(t, len(branches), 1) + assert.Equal(t, len(branches[0]), 0) + bytes, err := (&Store{}).EmitPlainFile(branches) + assert.Nil(t, err) + assert.Equal(t, ``, string(bytes)) +} +*/ + +func TestEmitValue(t *testing.T) { + // First iteration: load and store + bytes, err := (&Store{}).EmitValue(BRANCHES[0]) + assert.Nil(t, err) + assert.Equal(t, string(PLAIN_0), string(bytes)) + assert.Equal(t, PLAIN_0, bytes) +} From fbc87aea1421a50648973f39bf9aee43b7754d38 Mon Sep 17 00:00:00 2001 From: David Jacob Date: Thu, 25 Feb 2021 15:35:09 +0100 Subject: [PATCH 34/40] Update aws-sdk-go to version v1.37.18 (#823) --- go.mod | 4 ++-- go.sum | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 4defa0447..3799fb843 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/Azure/go-autorest/autorest/validation v0.2.0 // indirect github.com/Microsoft/go-winio v0.4.14 // indirect github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect - github.com/aws/aws-sdk-go v1.33.18 + github.com/aws/aws-sdk-go v1.37.18 github.com/blang/semver v3.5.1+incompatible github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc // indirect @@ -40,7 +40,7 @@ require ( github.com/stretchr/testify v1.5.1 go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 - golang.org/x/net v0.0.0-20200226121028-0de0cce0169b + golang.org/x/net v0.0.0-20201110031124-69a78807bb2b golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 // indirect google.golang.org/api v0.7.0 diff --git a/go.sum b/go.sum index dcc5988c2..d865ef210 100644 --- a/go.sum +++ b/go.sum @@ -48,8 +48,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aws/aws-sdk-go v1.33.18 h1:Ccy1SV2SsgJU3rfrD+SOhQ0jvuzfrFuja/oKI86ruPw= -github.com/aws/aws-sdk-go v1.33.18/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.37.18 h1:SRdWLg+DqMFWX8HB3UvXyAoZpw9IDIUYnSTwgzOYbqg= +github.com/aws/aws-sdk-go v1.37.18/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= @@ -85,7 +85,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -168,8 +167,10 @@ github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKe github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -268,6 +269,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -293,9 +295,8 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= @@ -323,6 +324,7 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43 h1:SgQ6LNaYJU0JIuEHv9+s6EbhSCwYeAf5Yvj6lpYlqAE= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= @@ -332,6 +334,8 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -408,6 +412,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc h1:XANm4xAMEQhRdWKqaL0qmhGDv7RuobwCO97TIlktaQE= gopkg.in/yaml.v3 v3.0.0-20210107172259-749611fa9fcc/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= From f37e612d54e8e2dab1b70288c945edc3f7e178e1 Mon Sep 17 00:00:00 2001 From: leigh capili Date: Sun, 28 Feb 2021 13:06:13 -0700 Subject: [PATCH 35/40] Fix broken sops config anchor in README Signed-off-by: leigh capili --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 603356c21..e503bb405 100644 --- a/README.rst +++ b/README.rst @@ -372,7 +372,7 @@ The sops team recommends the ``updatekeys`` approach. ``updatekeys`` command ********************** -The ``updatekeys`` command uses the `.sops.yaml <#29using-sopsyaml-conf-to-select-kmspgp-for-new-files>`_ +The ``updatekeys`` command uses the `.sops.yaml <#using-sops-yaml-conf-to-select-kms-pgp-for-new-files>`_ configuration file to update (add or remove) the corresponding secrets in the encrypted file. Note that the example below uses the `Block Scalar yaml construct `_ to build a space From 79d5dac9ffe8ca3f4214f6aba6d157dce89cbbab Mon Sep 17 00:00:00 2001 From: Brice Colucci Date: Wed, 10 Mar 2021 15:23:11 -0500 Subject: [PATCH 36/40] feat: Support more complicated path_regexp (issues/826) (#829) * feat: Support more complicated path_regexp (https://github.com/mozilla/sops/issues/826) * feat: Support more complicated path_regexp (https://github.com/mozilla/sops/issues/826) * fix review: do not panic and return an error instead if the regexp is not valid. * fix merge mess Co-authored-by: AJ Bahnken <1144310+ajvb@users.noreply.github.com> --- config/config.go | 14 ++++++++------ config/config_test.go | 36 ++++++++++++++++++++++++++++++++++++ go.sum | 2 -- 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/config/config.go b/config/config.go index 18a71c3df..e89336ddc 100644 --- a/config/config.go +++ b/config/config.go @@ -10,7 +10,6 @@ import ( "path" "regexp" - "gopkg.in/yaml.v3" "github.com/sirupsen/logrus" "go.mozilla.org/sops/v3" "go.mozilla.org/sops/v3/age" @@ -21,6 +20,7 @@ import ( "go.mozilla.org/sops/v3/logging" "go.mozilla.org/sops/v3/pgp" "go.mozilla.org/sops/v3/publish" + "gopkg.in/yaml.v3" ) var log *logrus.Logger @@ -326,11 +326,13 @@ func parseCreationRuleForFile(conf *configFile, filePath string, kmsEncryptionCo rule = &r break } - if r.PathRegex != "" { - if match, _ := regexp.MatchString(r.PathRegex, filePath); match { - rule = &r - break - } + reg, err := regexp.Compile(r.PathRegex) + if err != nil { + return nil, fmt.Errorf("can not compile regexp: %w", err) + } + if reg.MatchString(filePath) { + rule = &r + break } } diff --git a/config/config_test.go b/config/config_test.go index 183eb7836..ac8aca6f3 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -208,6 +208,24 @@ destination_rules: path_regex: "vault-v1/*" `) +var sampleConfigWithInvalidComplicatedRegexp = []byte(` +creation_rules: + - path_regex: "[ ]\\K(? Date: Wed, 10 Mar 2021 17:37:53 -0300 Subject: [PATCH 37/40] Match file path relative to config file's directory (#827) * Match file path relative to config file's directory * Update README.rst * Remove metadata field from configFile yaml-oriented struct --- README.rst | 2 +- config/config.go | 15 ++++++++++++-- config/config_test.go | 47 +++++++++++++++++++++++++++++-------------- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/README.rst b/README.rst index 4c4ed0eec..53800f8c7 100644 --- a/README.rst +++ b/README.rst @@ -650,7 +650,7 @@ 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: +The path_regex checks the path of the encrypting file relative to the .sops.yaml config 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 diff --git a/config/config.go b/config/config.go index e89336ddc..061d038e2 100644 --- a/config/config.go +++ b/config/config.go @@ -8,7 +8,9 @@ import ( "io/ioutil" "os" "path" + "path/filepath" "regexp" + "strings" "github.com/sirupsen/logrus" "go.mozilla.org/sops/v3" @@ -313,12 +315,20 @@ func parseDestinationRuleForFile(conf *configFile, filePath string, kmsEncryptio return config, nil } -func parseCreationRuleForFile(conf *configFile, filePath string, kmsEncryptionContext map[string]*string) (*Config, error) { +func parseCreationRuleForFile(conf *configFile, confPath, filePath string, kmsEncryptionContext map[string]*string) (*Config, error) { // If config file doesn't contain CreationRules (it's empty or only contains DestionationRules), assume it does not exist if conf.CreationRules == nil { return nil, nil } + configDir, err := filepath.Abs(filepath.Dir(confPath)) + if err != nil { + return nil, err + } + + // compare file path relative to path of config file + filePath = strings.TrimPrefix(filePath, configDir + string(filepath.Separator)) + var rule *creationRule for _, r := range conf.CreationRules { @@ -356,7 +366,8 @@ func LoadCreationRuleForFile(confPath string, filePath string, kmsEncryptionCont if err != nil { return nil, err } - return parseCreationRuleForFile(conf, filePath, kmsEncryptionContext) + + return parseCreationRuleForFile(conf, confPath, filePath, kmsEncryptionContext) } // LoadDestinationRuleForFile works the same as LoadCreationRuleForFile, but gets the "creation_rule" from the matching destination_rule's diff --git a/config/config_test.go b/config/config_test.go index ac8aca6f3..c1d723417 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -75,6 +75,15 @@ creation_rules: hc_vault_uris: https://foz:443/v1/foz/keys/foz `) +var sampleConfigWithAmbiguousPath = []byte(` +creation_rules: + - path_regex: foo/* + kms: "1" + pgp: "2" + gcp_kms: "3" + hc_vault_uris: http://4:8200/v1/4/keys/4 +`) + var sampleConfigWithGroups = []byte(` creation_rules: - path_regex: foobar* @@ -299,7 +308,7 @@ func TestLoadConfigFileWithGroups(t *testing.T) { } func TestLoadConfigFileWithNoMatchingRules(t *testing.T) { - _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithNoMatchingRules, t), "foobar2000", nil) + _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithNoMatchingRules, t), "/conf/path", "foobar2000", nil) assert.NotNil(t, err) } @@ -322,51 +331,51 @@ func TestLoadConfigFileWithComplicatedRegexp(t *testing.T) { } func TestLoadEmptyConfigFile(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleEmptyConfig, t), "foobar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleEmptyConfig, t), "/conf/path", "foobar2000", nil) assert.Nil(t, conf) assert.Nil(t, err) } func TestLoadConfigFileWithEmptyCreationRules(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithEmptyCreationRules, t), "foobar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithEmptyCreationRules, t), "/conf/path", "foobar2000", nil) assert.Nil(t, conf) assert.Nil(t, err) } func TestLoadConfigFileWithOnlyDestinationRules(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithOnlyDestinationRules, t), "foobar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithOnlyDestinationRules, t), "/conf/path", "foobar2000", nil) assert.Nil(t, conf) assert.Nil(t, err) } func TestKeyGroupsForFile(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "foobar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "/conf/path", "foobar2000", nil) assert.Nil(t, err) assert.Equal(t, "2", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "1", conf.KeyGroups[0][1].ToString()) - conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "whatever", nil) + conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "/conf/path", "whatever", nil) assert.Nil(t, err) assert.Equal(t, "bar", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "foo", conf.KeyGroups[0][1].ToString()) } func TestKeyGroupsForFileWithPath(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithPath, t), "foo/bar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithPath, t), "/conf/path", "foo/bar2000", nil) assert.Nil(t, err) assert.Equal(t, "2", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "1", conf.KeyGroups[0][1].ToString()) - conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfigWithPath, t), "somefilename.yml", nil) + conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfigWithPath, t), "/conf/path", "somefilename.yml", nil) assert.Nil(t, err) assert.Equal(t, "baggins", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "bilbo", conf.KeyGroups[0][1].ToString()) - conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "whatever", nil) + conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "/conf/path", "whatever", nil) assert.Nil(t, err) assert.Equal(t, "bar", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "foo", conf.KeyGroups[0][1].ToString()) } func TestKeyGroupsForFileWithGroups(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithGroups, t), "whatever", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithGroups, t), "/conf/path", "whatever", nil) assert.Nil(t, err) assert.Equal(t, "bar", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "foo", conf.KeyGroups[0][1].ToString()) @@ -375,31 +384,39 @@ func TestKeyGroupsForFileWithGroups(t *testing.T) { } func TestLoadConfigFileWithUnencryptedSuffix(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithSuffixParameters, t), "foobar", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithSuffixParameters, t), "/conf/path", "foobar", nil) assert.Nil(t, err) assert.Equal(t, "_unencrypted", conf.UnencryptedSuffix) } func TestLoadConfigFileWithEncryptedSuffix(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithSuffixParameters, t), "barfoo", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithSuffixParameters, t), "/conf/path", "barfoo", nil) assert.Nil(t, err) assert.Equal(t, "_enc", conf.EncryptedSuffix) } func TestLoadConfigFileWithUnencryptedRegex(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithRegexParameters, t), "barbar", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithRegexParameters, t), "/conf/path", "barbar", nil) assert.Equal(t, nil, err) assert.Equal(t, "^dec:", conf.UnencryptedRegex) } func TestLoadConfigFileWithEncryptedRegex(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithRegexParameters, t), "barbar", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithRegexParameters, t), "/conf/path", "barbar", nil) assert.Equal(t, nil, err) assert.Equal(t, "^enc:", conf.EncryptedRegex) } func TestLoadConfigFileWithInvalidParameters(t *testing.T) { - _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithInvalidParameters, t), "foobar", nil) + _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithInvalidParameters, t), "/conf/path", "foobar", nil) + assert.NotNil(t, err) +} + +func TestLoadConfigFileWithAmbiguousPath(t *testing.T) { + config := parseConfigFile(sampleConfigWithAmbiguousPath, t) + _, err := parseCreationRuleForFile(config, "/foo/config", "/foo/foo/bar", nil) + assert.Nil(t, err) + _, err = parseCreationRuleForFile(config, "/foo/config", "/foo/fuu/bar", nil) assert.NotNil(t, err) } From c178f896629e7b7eb684ec96fe22d8e2ad9024b4 Mon Sep 17 00:00:00 2001 From: Adrian Utrilla Date: Wed, 10 Mar 2021 21:47:43 +0100 Subject: [PATCH 38/40] Revert "Match file path relative to config file's directory (#827)" This reverts commit dd7ce3d2cb25e2e913a344572b64b81e6b9a947e. --- README.rst | 2 +- config/config.go | 15 ++------------ config/config_test.go | 47 ++++++++++++++----------------------------- 3 files changed, 18 insertions(+), 46 deletions(-) diff --git a/README.rst b/README.rst index 53800f8c7..4c4ed0eec 100644 --- a/README.rst +++ b/README.rst @@ -650,7 +650,7 @@ 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 path of the encrypting file relative to the .sops.yaml config file. Here is another example: +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 diff --git a/config/config.go b/config/config.go index 061d038e2..e89336ddc 100644 --- a/config/config.go +++ b/config/config.go @@ -8,9 +8,7 @@ import ( "io/ioutil" "os" "path" - "path/filepath" "regexp" - "strings" "github.com/sirupsen/logrus" "go.mozilla.org/sops/v3" @@ -315,20 +313,12 @@ func parseDestinationRuleForFile(conf *configFile, filePath string, kmsEncryptio return config, nil } -func parseCreationRuleForFile(conf *configFile, confPath, filePath string, kmsEncryptionContext map[string]*string) (*Config, error) { +func parseCreationRuleForFile(conf *configFile, filePath string, kmsEncryptionContext map[string]*string) (*Config, error) { // If config file doesn't contain CreationRules (it's empty or only contains DestionationRules), assume it does not exist if conf.CreationRules == nil { return nil, nil } - configDir, err := filepath.Abs(filepath.Dir(confPath)) - if err != nil { - return nil, err - } - - // compare file path relative to path of config file - filePath = strings.TrimPrefix(filePath, configDir + string(filepath.Separator)) - var rule *creationRule for _, r := range conf.CreationRules { @@ -366,8 +356,7 @@ func LoadCreationRuleForFile(confPath string, filePath string, kmsEncryptionCont if err != nil { return nil, err } - - return parseCreationRuleForFile(conf, confPath, filePath, kmsEncryptionContext) + return parseCreationRuleForFile(conf, filePath, kmsEncryptionContext) } // LoadDestinationRuleForFile works the same as LoadCreationRuleForFile, but gets the "creation_rule" from the matching destination_rule's diff --git a/config/config_test.go b/config/config_test.go index c1d723417..ac8aca6f3 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -75,15 +75,6 @@ creation_rules: hc_vault_uris: https://foz:443/v1/foz/keys/foz `) -var sampleConfigWithAmbiguousPath = []byte(` -creation_rules: - - path_regex: foo/* - kms: "1" - pgp: "2" - gcp_kms: "3" - hc_vault_uris: http://4:8200/v1/4/keys/4 -`) - var sampleConfigWithGroups = []byte(` creation_rules: - path_regex: foobar* @@ -308,7 +299,7 @@ func TestLoadConfigFileWithGroups(t *testing.T) { } func TestLoadConfigFileWithNoMatchingRules(t *testing.T) { - _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithNoMatchingRules, t), "/conf/path", "foobar2000", nil) + _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithNoMatchingRules, t), "foobar2000", nil) assert.NotNil(t, err) } @@ -331,51 +322,51 @@ func TestLoadConfigFileWithComplicatedRegexp(t *testing.T) { } func TestLoadEmptyConfigFile(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleEmptyConfig, t), "/conf/path", "foobar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleEmptyConfig, t), "foobar2000", nil) assert.Nil(t, conf) assert.Nil(t, err) } func TestLoadConfigFileWithEmptyCreationRules(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithEmptyCreationRules, t), "/conf/path", "foobar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithEmptyCreationRules, t), "foobar2000", nil) assert.Nil(t, conf) assert.Nil(t, err) } func TestLoadConfigFileWithOnlyDestinationRules(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithOnlyDestinationRules, t), "/conf/path", "foobar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithOnlyDestinationRules, t), "foobar2000", nil) assert.Nil(t, conf) assert.Nil(t, err) } func TestKeyGroupsForFile(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "/conf/path", "foobar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "foobar2000", nil) assert.Nil(t, err) assert.Equal(t, "2", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "1", conf.KeyGroups[0][1].ToString()) - conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "/conf/path", "whatever", nil) + conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "whatever", nil) assert.Nil(t, err) assert.Equal(t, "bar", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "foo", conf.KeyGroups[0][1].ToString()) } func TestKeyGroupsForFileWithPath(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithPath, t), "/conf/path", "foo/bar2000", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithPath, t), "foo/bar2000", nil) assert.Nil(t, err) assert.Equal(t, "2", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "1", conf.KeyGroups[0][1].ToString()) - conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfigWithPath, t), "/conf/path", "somefilename.yml", nil) + conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfigWithPath, t), "somefilename.yml", nil) assert.Nil(t, err) assert.Equal(t, "baggins", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "bilbo", conf.KeyGroups[0][1].ToString()) - conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "/conf/path", "whatever", nil) + conf, err = parseCreationRuleForFile(parseConfigFile(sampleConfig, t), "whatever", nil) assert.Nil(t, err) assert.Equal(t, "bar", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "foo", conf.KeyGroups[0][1].ToString()) } func TestKeyGroupsForFileWithGroups(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithGroups, t), "/conf/path", "whatever", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithGroups, t), "whatever", nil) assert.Nil(t, err) assert.Equal(t, "bar", conf.KeyGroups[0][0].ToString()) assert.Equal(t, "foo", conf.KeyGroups[0][1].ToString()) @@ -384,39 +375,31 @@ func TestKeyGroupsForFileWithGroups(t *testing.T) { } func TestLoadConfigFileWithUnencryptedSuffix(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithSuffixParameters, t), "/conf/path", "foobar", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithSuffixParameters, t), "foobar", nil) assert.Nil(t, err) assert.Equal(t, "_unencrypted", conf.UnencryptedSuffix) } func TestLoadConfigFileWithEncryptedSuffix(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithSuffixParameters, t), "/conf/path", "barfoo", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithSuffixParameters, t), "barfoo", nil) assert.Nil(t, err) assert.Equal(t, "_enc", conf.EncryptedSuffix) } func TestLoadConfigFileWithUnencryptedRegex(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithRegexParameters, t), "/conf/path", "barbar", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithRegexParameters, t), "barbar", nil) assert.Equal(t, nil, err) assert.Equal(t, "^dec:", conf.UnencryptedRegex) } func TestLoadConfigFileWithEncryptedRegex(t *testing.T) { - conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithRegexParameters, t), "/conf/path", "barbar", nil) + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithRegexParameters, t), "barbar", nil) assert.Equal(t, nil, err) assert.Equal(t, "^enc:", conf.EncryptedRegex) } func TestLoadConfigFileWithInvalidParameters(t *testing.T) { - _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithInvalidParameters, t), "/conf/path", "foobar", nil) - assert.NotNil(t, err) -} - -func TestLoadConfigFileWithAmbiguousPath(t *testing.T) { - config := parseConfigFile(sampleConfigWithAmbiguousPath, t) - _, err := parseCreationRuleForFile(config, "/foo/config", "/foo/foo/bar", nil) - assert.Nil(t, err) - _, err = parseCreationRuleForFile(config, "/foo/config", "/foo/fuu/bar", nil) + _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithInvalidParameters, t), "foobar", nil) assert.NotNil(t, err) } From cb4229fe37ff28c9d348fedf568dd4c06d36b6cb Mon Sep 17 00:00:00 2001 From: AJ Bahnken Date: Wed, 24 Mar 2021 14:29:00 -0700 Subject: [PATCH 39/40] Prep for v3.7.0 --- CHANGELOG.rst | 15 +++++++++++++-- version/version.go | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e8c78fd88..9ced187ba 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,17 +1,28 @@ Changelog ========= -Develop branch --------------- +3.7.0 +----- +Features: + + * Add support for age (#688) + * Add filename to exec-file (#761) Changes: * Comments at the beginning of YAML documents are now no longer discarded (#756) + * On failed decryption with GPG, return the error returned by GPG to the sops user (#762) + * Use yaml.v3 instead of modified yaml.v2 for handling YAML files (#791) + * Update aws-sdk-go to version v1.37.18 (#823) Bug fixes: * Fix several problems with YAML comment handling described in #695 (#754) +Project Changes: + + * Switch from TravisCI to Github Actions (#792) + 3.6.1 ----- Features: diff --git a/version/version.go b/version/version.go index 4093f7363..cbcff60f0 100644 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ import ( ) // Version represents the value of the current semantic version -const Version = "3.6.1" +const Version = "3.7.0" // PrintVersion handles the version command for sops func PrintVersion(c *cli.Context) { From e8076909ef57489a136e66d788e01fd413d72a54 Mon Sep 17 00:00:00 2001 From: AJ Bahnken Date: Wed, 24 Mar 2021 15:30:50 -0700 Subject: [PATCH 40/40] Small changelog fix for v3.7 --- CHANGELOG.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9ced187ba..5a3049738 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,15 +10,10 @@ Features: Changes: - * Comments at the beginning of YAML documents are now no longer discarded (#756) * On failed decryption with GPG, return the error returned by GPG to the sops user (#762) * Use yaml.v3 instead of modified yaml.v2 for handling YAML files (#791) * Update aws-sdk-go to version v1.37.18 (#823) -Bug fixes: - - * Fix several problems with YAML comment handling described in #695 (#754) - Project Changes: * Switch from TravisCI to Github Actions (#792)