1
0
mirror of https://github.com/getsops/sops.git synced 2026-02-05 12:45:21 +01:00

Added YAML encryption

This commit is contained in:
Adrian Utrilla
2016-08-18 15:49:27 -07:00
parent 3997384272
commit 0fbba59163
6 changed files with 83 additions and 8 deletions

View File

@@ -8,7 +8,8 @@ import (
)
type JSONStore struct {
Data map[string]interface{}
Data map[string]interface{}
metadata sops.Metadata
}
func (store *JSONStore) WalkValue(in interface{}, additionalAuthData string, onLeaves func(interface{}, string) (interface{}, error)) (interface{}, error) {
@@ -107,3 +108,7 @@ func (store JSONStore) LoadMetadata(in string) error {
func (store JSONStore) Metadata() sops.Metadata {
return sops.Metadata{}
}
func (store *JSONStore) SetMetadata(metadata sops.Metadata) {
store.metadata = metadata
}

View File

@@ -127,3 +127,14 @@ func (k KMSMasterKey) createSession() (*session.Session, error) {
}
return sess, nil
}
func (k KMSMasterKey) ToMap() map[string]string {
out := make(map[string]string)
out["arn"] = k.Arn
if k.Role != "" {
out["role"] = k.Role
}
out["created_at"] = k.CreationDate.Format("2006-01-02T15:04:05Z")
out["enc"] = k.EncryptedKey
return out
}

View File

@@ -87,6 +87,7 @@ func main() {
cli.StringFlag{
Name: "unencrypted-suffix",
Usage: "override the unencrypted key suffix. default: unencrypted_",
Value: sops.DefaultUnencryptedSuffix,
},
cli.StringFlag{
Name: "config",
@@ -175,9 +176,10 @@ func decrypt(c *cli.Context, file string, fileBytes []byte) error {
return cli.NewExitError(err.Error(), 4)
}
err = store.Load(string(fileBytes), key)
fmt.Println(err == sops.MacMismatch)
if err == sops.MacMismatch && !c.Bool("ignore-mac") {
return cli.NewExitError("MAC mismatch", 5)
} else if err != nil {
} else if err != sops.MacMismatch {
return cli.NewExitError(fmt.Sprintf("Error loading file: %s", err), 6)
}
s, err := store.DumpUnencrypted()
@@ -195,6 +197,8 @@ func encrypt(c *cli.Context, file string, fileBytes []byte) error {
return cli.NewExitError(fmt.Sprintf("Error loading file: %s", err), 4)
}
var metadata sops.Metadata
metadata.UnencryptedSuffix = c.String("unencrypted-suffix")
metadata.Version = "2.0.0"
var kmsKeys []sops.MasterKey
if c.String("kms") != "" {
for _, k := range kms.KMSMasterKeysFromArnString(c.String("kms")) {
@@ -221,6 +225,7 @@ func encrypt(c *cli.Context, file string, fileBytes []byte) error {
}
}
store.SetMetadata(metadata)
out, err := store.Dump(string(key))
fmt.Println(out)
return nil

View File

@@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"github.com/howeyc/gopass"
"go.mozilla.org/sops"
"go.mozilla.org/sops/gpgagent"
"golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/armor"
@@ -187,3 +188,11 @@ func (key *GPGMasterKey) passphrasePrompt(keys []openpgp.Key, symmetric bool) ([
}
return nil, fmt.Errorf("No key to unlock")
}
func (key GPGMasterKey) ToMap() map[string]string {
out := make(map[string]string)
out["fp"] = key.Fingerprint
out["created_at"] = key.CreationDate.Format(sops.DateFormat)
out["enc"] = key.EncryptedKey
return out
}

22
sops.go
View File

@@ -5,6 +5,10 @@ import (
"time"
)
const DateFormat = "2006-01-02T15:04:05Z"
const DefaultUnencryptedSuffix = "_unencrypted"
type Error string
func (e Error) Error() string { return string(e) }
@@ -30,6 +34,7 @@ type MasterKey interface {
Decrypt() (string, error)
NeedsRotation() bool
ToString() string
ToMap() map[string]string
}
type Store interface {
@@ -39,6 +44,7 @@ type Store interface {
DumpUnencrypted() (string, error)
Metadata() Metadata
LoadMetadata(in string) error
SetMetadata(Metadata)
}
func (m *Metadata) MasterKeyCount() int {
@@ -71,3 +77,19 @@ func (m *Metadata) UpdateMasterKeys(dataKey string) {
}
}
}
func (m *Metadata) ToMap() map[string]interface{} {
out := make(map[string]interface{})
out["lastmodified"] = m.LastModified.Format("2006-01-02T15:04:05Z")
out["unencrypted_suffix"] = m.UnencryptedSuffix
out["mac"] = m.MessageAuthenticationCode
out["version"] = m.Version
for _, ks := range m.KeySources {
keys := make([]map[string]string, 0)
for _, k := range ks.Keys {
keys = append(keys, k.ToMap())
}
out[ks.Name] = keys
}
return out
}

View File

@@ -3,11 +3,12 @@ package yaml
import (
"crypto/sha512"
"fmt"
"github.com/autrilla/yaml"
"go.mozilla.org/sops"
"go.mozilla.org/sops/decryptor"
"go.mozilla.org/sops/kms"
"go.mozilla.org/sops/pgp"
"gopkg.in/yaml.v2"
"os"
"strconv"
"time"
)
@@ -123,7 +124,7 @@ func (store *YAMLStore) Load(data, key string) error {
if err != nil {
return fmt.Errorf("Error walking tree: %s", err)
}
originalMac, err := decryptor.Decrypt(store.metadata.MessageAuthenticationCode, key, []byte(store.metadata.LastModified.Format("2006-01-02T15:04:05Z")))
originalMac, err := decryptor.Decrypt(store.metadata.MessageAuthenticationCode, key, []byte(store.metadata.LastModified.Format(sops.DateFormat)))
if err != nil {
return fmt.Errorf("Error decrypting MAC: %s", err)
}
@@ -135,12 +136,30 @@ func (store *YAMLStore) Load(data, key string) error {
}
func (store *YAMLStore) Dump(key string) (string, error) {
hash := sha512.New()
_, err := store.WalkValue(store.Data, "", func(in interface{}, additionalAuthData string) (interface{}, error) {
return decryptor.Encrypt(in, key, []byte(additionalAuthData))
v, err := decryptor.Encrypt(in, key, []byte(additionalAuthData))
if err != nil {
return nil, err
}
bytes, err := toBytes(in)
if err != nil {
return nil, err
}
hash.Write(bytes)
return v, err
})
if err != nil {
return "", fmt.Errorf("Error walking tree: %s", err)
}
mac := fmt.Sprintf("%X", hash.Sum(nil))
os.Stderr.WriteString(mac)
store.metadata.MessageAuthenticationCode, err = decryptor.Encrypt(mac, key, []byte(store.metadata.LastModified.Format(sops.DateFormat)))
if err != nil {
return "", fmt.Errorf("Error encrypting MAC: %s", err)
}
store.Data = append(store.Data, yaml.MapItem{Key: "sops", Value: store.metadata.ToMap()})
out, err := yaml.Marshal(store.Data)
if err != nil {
return "", fmt.Errorf("Error marshaling to yaml: %s", err)
@@ -173,7 +192,7 @@ func (store *YAMLStore) LoadMetadata(in string) error {
return err
}
store.metadata.MessageAuthenticationCode = data["mac"].(string)
lastModified, err := time.Parse("2006-01-02T15:04:05Z", data["lastmodified"].(string))
lastModified, err := time.Parse(sops.DateFormat, data["lastmodified"].(string))
if err != nil {
return fmt.Errorf("Could not parse last modified date: %s", err)
}
@@ -213,7 +232,7 @@ func (store *YAMLStore) kmsEntries(in []interface{}) (sops.KeySource, error) {
if ok {
key.Role = role
}
creationDate, err := time.Parse("2006-01-02T15:04:05Z", entry["created_at"].(string))
creationDate, err := time.Parse(sops.DateFormat, entry["created_at"].(string))
if err != nil {
return keysource, fmt.Errorf("Could not parse creation date: %s", err)
}
@@ -231,7 +250,7 @@ func (store *YAMLStore) pgpEntries(in []interface{}) (sops.KeySource, error) {
key := &pgp.GPGMasterKey{}
key.Fingerprint = entry["fp"].(string)
key.EncryptedKey = entry["enc"].(string)
creationDate, err := time.Parse("2006-01-02T15:04:05Z", entry["created_at"].(string))
creationDate, err := time.Parse(sops.DateFormat, entry["created_at"].(string))
if err != nil {
return keysource, fmt.Errorf("Could not parse creation date: %s", err)
}
@@ -240,3 +259,7 @@ func (store *YAMLStore) pgpEntries(in []interface{}) (sops.KeySource, error) {
}
return keysource, nil
}
func (store *YAMLStore) SetMetadata(metadata sops.Metadata) {
store.metadata = metadata
}