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:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
22
sops.go
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user