This commit is contained in:
Calin Don 2017-09-12 15:36:48 +03:00
Родитель f57598d02c
Коммит f7d72449b2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 984405B0B34726BF
5 изменённых файлов: 48 добавлений и 52 удалений

Просмотреть файл

@ -33,7 +33,7 @@ test:
gpg --import pgp/sops_functional_tests_key.asc 2>&1 1>/dev/null || exit 0
$(GO) test $(PROJECT)/pgp -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
$(GO) test $(PROJECT)/kms -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
$(GO) test $(PROJECT)/cloudkms -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
$(GO) test $(PROJECT)/gcpkms -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
showcoverage: test
$(GO) tool cover -html=coverage.out

Просмотреть файл

@ -21,7 +21,7 @@ import (
"github.com/google/shlex"
"go.mozilla.org/sops/aes"
"go.mozilla.org/sops/cloudkms"
"go.mozilla.org/sops/gcpkms"
"go.mozilla.org/sops/json"
"go.mozilla.org/sops/kms"
"go.mozilla.org/sops/pgp"
@ -92,7 +92,7 @@ func main() {
cli.VersionPrinter = printVersion
app := cli.NewApp()
app.Name = "sops"
app.Usage = "sops - encrypted file editor with AWS KMS, google cloud KMS and GPG support"
app.Usage = "sops - encrypted file editor with AWS KMS, GCP KMS and GPG support"
app.ArgsUsage = "sops [options] file"
app.Version = version
app.Authors = []cli.Author{
@ -105,8 +105,8 @@ func main() {
in the -k flag or in the SOPS_KMS_ARN environment variable.
(you need valid credentials in ~/.aws/credentials or in your env)
To encrypt or decrypt a document with google cloud KMS, specify the
cloud KMS resource Id in the -c flag or in the SOPS_CLOUD_KMS_IDS
To encrypt or decrypt a document with GCP KMS, specify the
GCP KMS resource ID in the --gcp-kms flag or in the SOPS_GCP_KMS_IDS
environment variable.
(you need to setup google application default credentials. See
https://developers.google.com/identity/protocols/application-default-credentials)
@ -121,7 +121,7 @@ func main() {
decrypting existing documents can be done with "sops file" or
"sops -d file" respectively. The KMS and PGP keys listed in the encrypted
documents are used then. To manage master keys in existing documents, use
the "add-{kms,pgp,cloud-kms}" and "rm-{kms,pgp,cloud-kms}" flags.
the "add-{kms,pgp,gcp-kms}" and "rm-{kms,pgp,gcp-kms}" flags.
To use a different GPG binary than the one in your PATH, set SOPS_GPG_EXEC.
@ -148,9 +148,9 @@ func main() {
EnvVar: "SOPS_KMS_ARN",
},
cli.StringFlag{
Name: "cloud-kms, c",
Usage: "comma separated list of google cloud KMS resource IDs",
EnvVar: "SOPS_CLOUD_KMS_IDS",
Name: "gcp-kms",
Usage: "comma separated list of GCP KMS resource IDs",
EnvVar: "SOPS_CGP_KMS_IDS",
},
cli.StringFlag{
Name: "pgp, p",
@ -178,12 +178,12 @@ func main() {
Usage: "display master encryption keys in the file during editing",
},
cli.StringFlag{
Name: "add-cloud-kms",
Usage: "add the provided comma-separated list of google cloud KMS key resource IDs to the list of master keys on the given file",
Name: "add-gcp-kms",
Usage: "add the provided comma-separated list of GCP KMS key resource IDs to the list of master keys on the given file",
},
cli.StringFlag{
Name: "rm-cloud-kms",
Usage: "remove the provided comma-separated list of google cloud KMS key resource IDs from the list of master keys on the given file",
Name: "rm-gcp-kms",
Usage: "remove the provided comma-separated list of GCP KMS key resource IDs from the list of master keys on the given file",
},
cli.StringFlag{
Name: "add-kms",
@ -230,7 +230,7 @@ func main() {
}
fileName := c.Args()[0]
if _, err := os.Stat(fileName); os.IsNotExist(err) {
if c.String("add-kms") != "" || c.String("add-pgp") != "" || c.String("add-cloud-kms") != "" || c.String("rm-kms") != "" || c.String("rm-pgp") != "" || c.String("rm-cloud-kms") != "" {
if c.String("add-kms") != "" || c.String("add-pgp") != "" || c.String("add-gcp-kms") != "" || c.String("rm-kms") != "" || c.String("rm-pgp") != "" || c.String("rm-gcp-kms") != "" {
return cli.NewExitError("Error: cannot add or remove keys on non-existent files, use `--kms` and `--pgp` instead.", 49)
}
if c.Bool("encrypt") || c.Bool("decrypt") || c.Bool("rotate") {
@ -423,8 +423,8 @@ func getKeySources(c *cli.Context, file string) ([]sops.KeySource, error) {
kmsKeys = append(kmsKeys, k)
}
}
if c.String("cloud-kms") != "" {
for _, k := range cloudkms.MasterKeysFromResourceIdString(c.String("cloud-kms")) {
if c.String("gcp-kms") != "" {
for _, k := range gcpkms.MasterKeysFromResourceIdString(c.String("gcp-kms")) {
cloudKmsKeys = append(cloudKmsKeys, k)
}
}
@ -434,7 +434,7 @@ func getKeySources(c *cli.Context, file string) ([]sops.KeySource, error) {
}
}
var err error
if c.String("kms") == "" && c.String("pgp") == "" && c.String("cloud-kms") == "" {
if c.String("kms") == "" && c.String("pgp") == "" && c.String("gcp-kms") == "" {
var confBytes []byte
if c.String("config") != "" {
confBytes, err = ioutil.ReadFile(c.String("config"))
@ -454,7 +454,7 @@ func getKeySources(c *cli.Context, file string) ([]sops.KeySource, error) {
}
kmsKs := sops.KeySource{Name: "kms", Keys: kmsKeys}
pgpKs := sops.KeySource{Name: "pgp", Keys: pgpKeys}
cloudKmsKs := sops.KeySource{Name: "cloud-kms", Keys: cloudKmsKeys}
cloudKmsKs := sops.KeySource{Name: "gcp_kms", Keys: cloudKmsKeys}
return []sops.KeySource{kmsKs, cloudKmsKs, pgpKs}, nil
}
@ -500,10 +500,10 @@ func rotate(c *cli.Context, tree sops.Tree, outputStore sops.Store) ([]byte, err
}
tree.Metadata.AddKMSMasterKeys(c.String("add-kms"), kmsEncryptionContext)
tree.Metadata.AddPGPMasterKeys(c.String("add-pgp"))
tree.Metadata.AddCloudKMSMasterKeys(c.String("add-cloud-kms"))
tree.Metadata.AddGCPKMSMasterKeys(c.String("add-gcp-kms"))
tree.Metadata.RemoveKMSMasterKeys(c.String("rm-kms"))
tree.Metadata.RemovePGPMasterKeys(c.String("rm-pgp"))
tree.Metadata.RemoveCloudKMSMasterKeys(c.String("rm-cloud-kms"))
tree.Metadata.RemoveGCPKMSMasterKeys(c.String("rm-gcp-kms"))
_, errs := tree.GenerateDataKey()
if len(errs) > 0 {
return nil, cli.NewExitError(fmt.Sprintf("Error encrypting the data key with one or more master keys: %s", errs), exitCouldNotRetrieveKey)

Просмотреть файл

@ -1,4 +1,4 @@
package cloudkms //import "go.mozilla.org/sops/cloudkms"
package gcpkms //import "go.mozilla.org/sops/gcpkms"
import (
"encoding/base64"
@ -13,30 +13,25 @@ import (
cloudkms "google.golang.org/api/cloudkms/v1"
)
// this needs to be a global var for unit tests to work (mockKMS redefines
// it in keysource_test.go)
// var kmsSvc kmsiface.KMSAPI
// var isMocked bool
// MasterKey is a cloud KMS key used to encrypt and decrypt sops' data key.
// MasterKey is a GCP KMS key used to encrypt and decrypt sops' data key.
type MasterKey struct {
ResourceId string
EncryptedKey string
CreationDate time.Time
}
// Encrypt takes a sops data key, encrypts it with cloud KMS and stores the result in the EncryptedKey field
// Encrypt takes a sops data key, encrypts it with GCP KMS and stores the result in the EncryptedKey field
func (key *MasterKey) Encrypt(dataKey []byte) error {
cloudkmsService, err := key.createCloudKMSService()
if err != nil {
return fmt.Errorf("Cannot create cloud KMS service: %v", err)
return fmt.Errorf("Cannot create GCP KMS service: %v", err)
}
req := &cloudkms.EncryptRequest{
Plaintext: base64.StdEncoding.EncodeToString(dataKey),
}
resp, err := cloudkmsService.Projects.Locations.KeyRings.CryptoKeys.Encrypt(key.ResourceId, req).Do()
if err != nil {
return fmt.Errorf("Failed to call cloud KMS encryption service: %v", err)
return fmt.Errorf("Failed to call GCP KMS encryption service: %v", err)
}
key.EncryptedKey = resp.Ciphertext
@ -51,11 +46,11 @@ func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error {
return nil
}
// Decrypt decrypts the EncryptedKey field with cloud KMS and returns the result.
// Decrypt decrypts the EncryptedKey field with CGP KMS and returns the result.
func (key *MasterKey) Decrypt() ([]byte, error) {
cloudkmsService, err := key.createCloudKMSService()
if err != nil {
return nil, fmt.Errorf("Cannot create cloud KMS service: %v", err)
return nil, fmt.Errorf("Cannot create GCP KMS service: %v", err)
}
req := &cloudkms.DecryptRequest{
@ -78,7 +73,7 @@ func (key *MasterKey) ToString() string {
return key.ResourceId
}
// NewMasterKeyFromResourceId takes an cloud KMS resource id string and returns a new MasterKey for that
// NewMasterKeyFromResourceId takes a GCP KMS resource ID string and returns a new MasterKey for that
func NewMasterKeyFromResourceId(resourceId string) *MasterKey {
k := &MasterKey{}
resourceId = strings.Replace(resourceId, " ", "", -1)
@ -87,8 +82,7 @@ func NewMasterKeyFromResourceId(resourceId string) *MasterKey {
return k
}
// MasterKeysFromResourceIdString takes a comma separated list of cloud KMS
// resourece IDs and returns a slice of new MasterKeys for them
// MasterKeysFromResourceIdString takes a comma separated list of GCP KMS resourece IDs and returns a slice of new MasterKeys for them
func MasterKeysFromResourceIdString(resourceId string) []*MasterKey {
var keys []*MasterKey
if resourceId == "" {

Просмотреть файл

@ -1,4 +1,4 @@
package cloudkms
package gcpkms
import (
"testing"
@ -7,7 +7,7 @@ import (
"github.com/stretchr/testify/assert"
)
func TestCloudKMSKeySourceFromString(t *testing.T) {
func TestGCPKMSKeySourceFromString(t *testing.T) {
s := "projects/sops-testing1/locations/global/keyRings/creds/cryptoKeys/key1, projects/sops-testing2/locations/global/keyRings/creds/cryptoKeys/key2"
ks := MasterKeysFromResourceIdString(s)
k1 := ks[0]

32
sops.go
Просмотреть файл

@ -43,7 +43,7 @@ import (
"strings"
"time"
"go.mozilla.org/sops/cloudkms"
"go.mozilla.org/sops/gcpkms"
"go.mozilla.org/sops/kms"
"go.mozilla.org/sops/pgp"
)
@ -386,14 +386,14 @@ func (m *Metadata) AddPGPMasterKeys(pgpFps string) {
}
}
// AddCloudKMSMasterKeys parses the input comma separated string of cloud KMS resource IDs, generates a KMS MasterKey for each resource ID, and then adds the keys to the cloud KMS KeySource
func (m *Metadata) AddCloudKMSMasterKeys(resourceIds string) {
// AddGCPKMSMasterKeys parses the input comma separated string of GCP KMS resource IDs, generates a MasterKey for each resource ID, and then adds the keys to the GCP KMS KeySource
func (m *Metadata) AddGCPKMSMasterKeys(resourceIds string) {
for i, ks := range m.KeySources {
if ks.Name == "cloud-kms" {
if ks.Name == "gcp_kms" {
var keys []MasterKey
for _, k := range cloudkms.MasterKeysFromResourceIdString(resourceIds) {
for _, k := range gcpkms.MasterKeysFromResourceIdString(resourceIds) {
keys = append(keys, k)
fmt.Printf("Adding new cloud KMS master key: %s\n", k.ResourceId)
fmt.Printf("Adding new GCP KMS master key: %s\n", k.ResourceId)
}
ks.Keys = append(ks.Keys, keys...)
m.KeySources[i] = ks
@ -434,10 +434,10 @@ func (m *Metadata) RemoveKMSMasterKeys(arns string) {
m.RemoveMasterKeys(keys)
}
// RemoveCloudKMSMasterKeys takes a comma separated string of cloud KMS resource IDs and removes the corresponding keys
func (m *Metadata) RemoveCloudKMSMasterKeys(resourceIds string) {
// RemoveGCPKMSMasterKeys takes a comma separated string of GCP KMS resource IDs and removes the corresponding keys
func (m *Metadata) RemoveGCPKMSMasterKeys(resourceIds string) {
var keys []MasterKey
for _, k := range cloudkms.MasterKeysFromResourceIdString(resourceIds) {
for _, k := range gcpkms.MasterKeysFromResourceIdString(resourceIds) {
keys = append(keys, k)
}
m.RemoveMasterKeys(keys)
@ -472,6 +472,8 @@ func (m Metadata) GetDataKey() ([]byte, error) {
keyType := "Unknown"
if _, ok := k.(*pgp.MasterKey); ok {
keyType = "GPG"
} else if _, ok := k.(*gcpkms.MasterKey); ok {
keyType = "GCP KMS"
} else if _, ok := k.(*kms.MasterKey); ok {
keyType = "KMS"
}
@ -528,8 +530,8 @@ func MapToMetadata(data map[string]interface{}) (Metadata, error) {
}
}
if cloudk, ok := data["cloud-kms"].([]interface{}); ok {
ks, err := mapCloudKMSEntriesToKeySource(cloudk)
if gcpk, ok := data["gcp_kms"].([]interface{}); ok {
ks, err := mapGCPKMSEntriesToKeySource(gcpk)
if err == nil {
metadata.KeySources = append(metadata.KeySources, ks)
}
@ -556,9 +558,9 @@ func convertToMapStringInterface(in map[interface{}]interface{}) (map[string]int
return m, nil
}
func mapCloudKMSEntriesToKeySource(in []interface{}) (KeySource, error) {
func mapGCPKMSEntriesToKeySource(in []interface{}) (KeySource, error) {
var keys []MasterKey
keysource := KeySource{Name: "cloud-kms", Keys: keys}
keysource := KeySource{Name: "gcp_kms", Keys: keys}
for _, v := range in {
entry, ok := v.(map[string]interface{})
if !ok {
@ -566,11 +568,11 @@ func mapCloudKMSEntriesToKeySource(in []interface{}) (KeySource, error) {
var err error
entry, err = convertToMapStringInterface(m)
if !ok || err != nil {
fmt.Println("Cloud KMS entry has invalid format, skipping...")
fmt.Println("GCP KMS entry has invalid format, skipping...")
continue
}
}
key := &cloudkms.MasterKey{}
key := &gcpkms.MasterKey{}
key.ResourceId = entry["resource_id"].(string)
key.EncryptedKey = entry["enc"].(string)
creationDate, err := time.Parse(time.RFC3339, entry["created_at"].(string))