зеркало из https://github.com/getsops/sops.git
Use KeyService for all encrypt and decrypt operations
This commit is contained in:
Родитель
745a0631ba
Коммит
10dd9b5441
|
@ -4,6 +4,8 @@ package keys
|
|||
type MasterKey interface {
|
||||
Encrypt(dataKey []byte) error
|
||||
EncryptIfNeeded(dataKey []byte) error
|
||||
EncryptedDataKey() []byte
|
||||
SetEncryptedDataKey([]byte)
|
||||
Decrypt() ([]byte, error)
|
||||
NeedsRotation() bool
|
||||
ToString() string
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package keyservice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"go.mozilla.org/sops/keys"
|
||||
"go.mozilla.org/sops/kms"
|
||||
"go.mozilla.org/sops/pgp"
|
||||
)
|
||||
|
||||
func KeyFromMasterKey(mk keys.MasterKey) Key {
|
||||
switch mk := mk.(type) {
|
||||
case *pgp.MasterKey:
|
||||
return Key{
|
||||
KeyType: &Key_GpgKey{
|
||||
GpgKey: &GpgKey{
|
||||
Fingerprint: mk.Fingerprint,
|
||||
},
|
||||
},
|
||||
}
|
||||
case *kms.MasterKey:
|
||||
var ctx map[string]string
|
||||
for k, v := range mk.EncryptionContext {
|
||||
ctx[k] = *v
|
||||
}
|
||||
return Key{
|
||||
KeyType: &Key_KmsKey{
|
||||
KmsKey: &KmsKey{
|
||||
Arn: mk.Arn,
|
||||
Role: mk.Role,
|
||||
Context: ctx,
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("Tried to convert unknown MasterKey type %T to keyservice.Key", mk))
|
||||
}
|
||||
}
|
|
@ -87,7 +87,6 @@ func (ks Server) Encrypt(ctx context.Context,
|
|||
|
||||
func (ks Server) Decrypt(ctx context.Context,
|
||||
req *DecryptRequest) (*DecryptResponse, error) {
|
||||
|
||||
key := *req.Key
|
||||
switch k := key.KeyType.(type) {
|
||||
case *Key_GpgKey:
|
||||
|
|
|
@ -31,6 +31,14 @@ type MasterKey struct {
|
|||
EncryptionContext map[string]*string
|
||||
}
|
||||
|
||||
func (key *MasterKey) EncryptedDataKey() []byte {
|
||||
return []byte(key.EncryptedKey)
|
||||
}
|
||||
|
||||
func (key *MasterKey) SetEncryptedDataKey(enc []byte) {
|
||||
key.EncryptedKey = string(enc)
|
||||
}
|
||||
|
||||
// Encrypt takes a sops data key, encrypts it with KMS and stores the result in the EncryptedKey field
|
||||
func (key *MasterKey) Encrypt(dataKey []byte) error {
|
||||
// isMocked is set by unit test to indicate that the KMS service
|
||||
|
|
|
@ -24,6 +24,14 @@ type MasterKey struct {
|
|||
CreationDate time.Time
|
||||
}
|
||||
|
||||
func (key *MasterKey) EncryptedDataKey() []byte {
|
||||
return []byte(key.EncryptedKey)
|
||||
}
|
||||
|
||||
func (key *MasterKey) SetEncryptedDataKey(enc []byte) {
|
||||
key.EncryptedKey = string(enc)
|
||||
}
|
||||
|
||||
// Encrypt encrypts the data key with the PGP key with the same fingerprint as the MasterKey. It looks for PGP public keys in $PGPHOME/pubring.gpg.
|
||||
func (key *MasterKey) Encrypt(dataKey []byte) error {
|
||||
ring, err := key.pubRing()
|
||||
|
|
76
sops.go
76
sops.go
|
@ -44,8 +44,10 @@ import (
|
|||
"time"
|
||||
|
||||
"go.mozilla.org/sops/keys"
|
||||
"go.mozilla.org/sops/keyservice"
|
||||
"go.mozilla.org/sops/kms"
|
||||
"go.mozilla.org/sops/pgp"
|
||||
"golang.org/x/net/context"
|
||||
)
|
||||
|
||||
// DefaultUnencryptedSuffix is the default suffix a TreeItem key has to end with for sops to leave its Value unencrypted
|
||||
|
@ -348,19 +350,39 @@ func (m *Metadata) UpdateMasterKeysIfNeeded(dataKey []byte) (errs []error) {
|
|||
return
|
||||
}
|
||||
|
||||
// UpdateMasterKeys encrypts the data key with all master keys
|
||||
func (m *Metadata) UpdateMasterKeys(dataKey []byte) (errs []error) {
|
||||
for _, ks := range m.KeySources {
|
||||
for _, k := range ks.Keys {
|
||||
err := k.Encrypt(dataKey)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed to encrypt new data key with master key %q: %v\n", k.ToString(), err))
|
||||
func (m *Metadata) UpdateMasterKeysWithKeyServices(dataKey []byte, svcs []keyservice.KeyServiceServer) (errs []error) {
|
||||
if len(svcs) == 0 {
|
||||
return []error{
|
||||
fmt.Errorf("No key services provided, can not update master keys."),
|
||||
}
|
||||
}
|
||||
for _, keysource := range m.KeySources {
|
||||
for _, key := range keysource.Keys {
|
||||
svcKey := keyservice.KeyFromMasterKey(key)
|
||||
for _, svc := range svcs {
|
||||
rsp, err := svc.Encrypt(context.Background(), &keyservice.EncryptRequest{
|
||||
Key: &svcKey,
|
||||
Plaintext: dataKey,
|
||||
})
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("Failed to encrypt new data key with master key %q: %v\n", key.ToString(), err))
|
||||
}
|
||||
key.SetEncryptedDataKey(rsp.Ciphertext)
|
||||
// Only need to encrypt the key successfully with one service
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateMasterKeys encrypts the data key with all master keys
|
||||
func (m *Metadata) UpdateMasterKeys(dataKey []byte) (errs []error) {
|
||||
return m.UpdateMasterKeysWithKeyServices(dataKey, []keyservice.KeyServiceServer{
|
||||
keyservice.Server{},
|
||||
})
|
||||
}
|
||||
|
||||
// AddPGPMasterKeys parses the input comma separated string of GPG fingerprints, generates a PGP MasterKey for each fingerprint, and adds the keys to the PGP KeySource
|
||||
func (m *Metadata) AddPGPMasterKeys(pgpFps string) {
|
||||
for i, ks := range m.KeySources {
|
||||
|
@ -426,25 +448,35 @@ func (m *Metadata) ToMap() map[string]interface{} {
|
|||
return out
|
||||
}
|
||||
|
||||
// GetDataKey retrieves the data key from the first MasterKey in the Metadata's KeySources that's able to return it.
|
||||
func (m Metadata) GetDataKey() ([]byte, error) {
|
||||
// GetDataKeyWithKeyServices retrieves the data key, asking KeyServices to decrypt it with each
|
||||
// MasterKey in the Metadata's KeySources until one of them succeeds.
|
||||
func (m Metadata) GetDataKeyWithKeyServices(svcs []keyservice.KeyServiceServer) ([]byte, error) {
|
||||
errMsg := "Could not decrypt the data key with any of the master keys:\n"
|
||||
for _, ks := range m.KeySources {
|
||||
for _, k := range ks.Keys {
|
||||
key, err := k.Decrypt()
|
||||
if err == nil {
|
||||
return key, nil
|
||||
for _, keysource := range m.KeySources {
|
||||
for _, key := range keysource.Keys {
|
||||
svcKey := keyservice.KeyFromMasterKey(key)
|
||||
for _, svc := range svcs {
|
||||
rsp, err := svc.Decrypt(
|
||||
context.Background(),
|
||||
&keyservice.DecryptRequest{
|
||||
Ciphertext: key.EncryptedDataKey(),
|
||||
Key: &svcKey,
|
||||
})
|
||||
if err != nil {
|
||||
errMsg += fmt.Sprintf("\t%s: %s", key.ToString(), err)
|
||||
continue
|
||||
}
|
||||
return rsp.Plaintext, nil
|
||||
}
|
||||
keyType := "Unknown"
|
||||
if _, ok := k.(*pgp.MasterKey); ok {
|
||||
keyType = "GPG"
|
||||
} else if _, ok := k.(*kms.MasterKey); ok {
|
||||
keyType = "KMS"
|
||||
}
|
||||
errMsg += fmt.Sprintf("\t[%s]: %s:\t%s\n", keyType, k.ToString(), err)
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf(errMsg)
|
||||
return nil, fmt.Errorf("%s", errMsg)
|
||||
}
|
||||
|
||||
// GetDataKey retrieves the data key from the first MasterKey in the Metadata's KeySources that's able to return it,
|
||||
// using the local KeyService
|
||||
func (m Metadata) GetDataKey() ([]byte, error) {
|
||||
return m.GetDataKeyWithKeyServices([]keyservice.KeyServiceServer{keyservice.Server{}})
|
||||
}
|
||||
|
||||
// ToBytes converts a string, int, float or bool to a byte representation.
|
||||
|
|
Загрузка…
Ссылка в новой задаче