зеркало из https://github.com/getsops/sops.git
Add support for age.
This commit is contained in:
Родитель
334be56818
Коммит
e8d00046e1
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
10
go.mod
10
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
|
||||
|
|
42
go.sum
42
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=
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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{
|
||||
|
|
Загрузка…
Ссылка в новой задаче