зеркало из https://github.com/getsops/sops.git
Fixed golint issues
This commit is contained in:
Родитель
e908f46228
Коммит
c9d63a838e
|
@ -10,7 +10,7 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
type EncryptedValue struct {
|
||||
type encryptedValue struct {
|
||||
data []byte
|
||||
iv []byte
|
||||
tag []byte
|
||||
|
@ -19,7 +19,7 @@ type EncryptedValue struct {
|
|||
|
||||
var encre = regexp.MustCompile(`^ENC\[AES256_GCM,data:(.+),iv:(.+),tag:(.+),type:(.+)\]`)
|
||||
|
||||
func parse(value string) (*EncryptedValue, error) {
|
||||
func parse(value string) (*encryptedValue, error) {
|
||||
matches := encre.FindStringSubmatch(value)
|
||||
if matches == nil {
|
||||
return nil, fmt.Errorf("Input string %s does not match sops' data format", value)
|
||||
|
@ -38,7 +38,7 @@ func parse(value string) (*EncryptedValue, error) {
|
|||
}
|
||||
datatype := string(matches[4])
|
||||
|
||||
return &EncryptedValue{data, iv, tag, datatype}, nil
|
||||
return &encryptedValue{data, iv, tag, datatype}, nil
|
||||
}
|
||||
|
||||
// Decrypt takes a sops-format value string and a key and returns the decrypted value.
|
||||
|
@ -79,6 +79,7 @@ func Decrypt(value string, key []byte, additionalAuthData []byte) (interface{},
|
|||
}
|
||||
}
|
||||
|
||||
// Encrypt takes one of (string, int, float, bool) and encrypts it with the provided key and additional auth data, returning a sops-format encrypted string.
|
||||
func Encrypt(value interface{}, key []byte, additionalAuthData []byte) (string, error) {
|
||||
aescipher, err := cryptoaes.NewCipher(key)
|
||||
if err != nil {
|
||||
|
|
|
@ -6,13 +6,16 @@ import (
|
|||
"go.mozilla.org/sops"
|
||||
"go.mozilla.org/sops/kms"
|
||||
"go.mozilla.org/sops/pgp"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type JSONStore struct {
|
||||
// Store handles storage of JSON data. It's not finished yet, and therefore you should not use it.
|
||||
type Store struct {
|
||||
}
|
||||
|
||||
func (store JSONStore) Load(in string) (sops.TreeBranch, error) {
|
||||
// Load takes an input json string and returns a sops tree branch
|
||||
func (store Store) Load(in string) (sops.TreeBranch, error) {
|
||||
var branch sops.TreeBranch
|
||||
err := json.Unmarshal([]byte(in), branch)
|
||||
if err != nil {
|
||||
|
@ -26,7 +29,8 @@ func (store JSONStore) Load(in string) (sops.TreeBranch, error) {
|
|||
return branch, nil
|
||||
}
|
||||
|
||||
func (store JSONStore) Dump(tree sops.TreeBranch) (string, error) {
|
||||
// Dump performs the opposite operation to Load, it takes a sops tree branch and returns a json formatted string
|
||||
func (store Store) Dump(tree sops.TreeBranch) (string, error) {
|
||||
out, err := json.Marshal(tree)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error marshaling to json: %s", err)
|
||||
|
@ -34,7 +38,8 @@ func (store JSONStore) Dump(tree sops.TreeBranch) (string, error) {
|
|||
return string(out), nil
|
||||
}
|
||||
|
||||
func (store JSONStore) DumpWithMetadata(tree sops.TreeBranch, metadata sops.Metadata) (string, error) {
|
||||
// DumpWithMetadata takes a sops tree branch and sops metadata and marshals them to json.
|
||||
func (store Store) DumpWithMetadata(tree sops.TreeBranch, metadata sops.Metadata) (string, error) {
|
||||
tree = append(tree, sops.TreeItem{Key: "sops", Value: metadata.ToMap()})
|
||||
out, err := json.Marshal(tree)
|
||||
if err != nil {
|
||||
|
@ -43,7 +48,9 @@ func (store JSONStore) DumpWithMetadata(tree sops.TreeBranch, metadata sops.Meta
|
|||
return string(out), nil
|
||||
}
|
||||
|
||||
func (store JSONStore) LoadMetadata(in string) (sops.Metadata, error) {
|
||||
// LoadMetadata takes a json string and extracts sops' metadata from it
|
||||
func (store Store) LoadMetadata(in string) (sops.Metadata, error) {
|
||||
var ok bool
|
||||
var metadata sops.Metadata
|
||||
data := make(map[string]interface{})
|
||||
if err := json.Unmarshal([]byte(in), &data); err != nil {
|
||||
|
@ -51,7 +58,7 @@ func (store JSONStore) LoadMetadata(in string) (sops.Metadata, error) {
|
|||
}
|
||||
data = data["sops"].(map[string]interface{})
|
||||
metadata.MessageAuthenticationCode = data["mac"].(string)
|
||||
lastModified, err := time.Parse(sops.DateFormat, data["lastmodified"].(string))
|
||||
lastModified, err := time.Parse(time.RFC3339, data["lastmodified"].(string))
|
||||
if err != nil {
|
||||
return metadata, fmt.Errorf("Could not parse last modified date: %s", err)
|
||||
}
|
||||
|
@ -77,7 +84,7 @@ func (store JSONStore) LoadMetadata(in string) (sops.Metadata, error) {
|
|||
return metadata, nil
|
||||
}
|
||||
|
||||
func (store JSONStore) kmsEntries(in []interface{}) (sops.KeySource, error) {
|
||||
func (store Store) kmsEntries(in []interface{}) (sops.KeySource, error) {
|
||||
var keys []sops.MasterKey
|
||||
keysource := sops.KeySource{Name: "kms", Keys: keys}
|
||||
for _, v := range in {
|
||||
|
@ -89,7 +96,7 @@ func (store JSONStore) kmsEntries(in []interface{}) (sops.KeySource, error) {
|
|||
if ok {
|
||||
key.Role = role
|
||||
}
|
||||
creationDate, err := time.Parse(sops.DateFormat, entry["created_at"].(string))
|
||||
creationDate, err := time.Parse(time.RFC3339, entry["created_at"].(string))
|
||||
if err != nil {
|
||||
return keysource, fmt.Errorf("Could not parse creation date: %s", err)
|
||||
}
|
||||
|
@ -99,7 +106,7 @@ func (store JSONStore) kmsEntries(in []interface{}) (sops.KeySource, error) {
|
|||
return keysource, nil
|
||||
}
|
||||
|
||||
func (store JSONStore) pgpEntries(in []interface{}) (sops.KeySource, error) {
|
||||
func (store Store) pgpEntries(in []interface{}) (sops.KeySource, error) {
|
||||
var keys []sops.MasterKey
|
||||
keysource := sops.KeySource{Name: "pgp", Keys: keys}
|
||||
for _, v := range in {
|
||||
|
@ -107,7 +114,7 @@ func (store JSONStore) pgpEntries(in []interface{}) (sops.KeySource, error) {
|
|||
key := &pgp.MasterKey{}
|
||||
key.Fingerprint = entry["fp"].(string)
|
||||
key.EncryptedKey = entry["enc"].(string)
|
||||
creationDate, err := time.Parse(sops.DateFormat, entry["created_at"].(string))
|
||||
creationDate, err := time.Parse(time.RFC3339, entry["created_at"].(string))
|
||||
if err != nil {
|
||||
return keysource, fmt.Errorf("Could not parse creation date: %s", err)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// MasterKey is a AWS KMS key used to encrypt and decrypt sops' data key.
|
||||
type MasterKey struct {
|
||||
Arn string
|
||||
Role string
|
||||
|
@ -21,6 +22,7 @@ type MasterKey struct {
|
|||
CreationDate time.Time
|
||||
}
|
||||
|
||||
// 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 {
|
||||
sess, err := key.createSession()
|
||||
if err != nil {
|
||||
|
@ -35,6 +37,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// EncryptIfNeeded encrypts the provided sops' data ket and encrypts it if it hasn't been encrypted yet
|
||||
func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error {
|
||||
if key.EncryptedKey == "" {
|
||||
return key.Encrypt(dataKey)
|
||||
|
@ -42,6 +45,7 @@ func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts the EncryptedKey field with AWS KMS and returns the result.
|
||||
func (key *MasterKey) Decrypt() ([]byte, error) {
|
||||
k, err := base64.StdEncoding.DecodeString(key.EncryptedKey)
|
||||
if err != nil {
|
||||
|
@ -60,14 +64,17 @@ func (key *MasterKey) Decrypt() ([]byte, error) {
|
|||
return decrypted.Plaintext, nil
|
||||
}
|
||||
|
||||
// NeedsRotation returns whether the data key needs to be rotated or not.
|
||||
func (key *MasterKey) NeedsRotation() bool {
|
||||
return time.Since(key.CreationDate) > (time.Hour * 24 * 30 * 6)
|
||||
}
|
||||
|
||||
// ToString converts the key to a string representation
|
||||
func (key *MasterKey) ToString() string {
|
||||
return key.Arn
|
||||
}
|
||||
|
||||
// NewMasterKeyFromArn takes an ARN string and returns a new MasterKey for that ARN
|
||||
func NewMasterKeyFromArn(arn string) MasterKey {
|
||||
k := MasterKey{}
|
||||
arn = strings.Replace(arn, " ", "", -1)
|
||||
|
@ -82,6 +89,7 @@ func NewMasterKeyFromArn(arn string) MasterKey {
|
|||
return k
|
||||
}
|
||||
|
||||
// MasterKeysFromArnString takes a comma separated list of AWS KMS ARNs and returns a slice of new MasterKeys for those ARNs
|
||||
func MasterKeysFromArnString(arn string) []MasterKey {
|
||||
var keys []MasterKey
|
||||
if arn == "" {
|
||||
|
@ -93,7 +101,7 @@ func MasterKeysFromArnString(arn string) []MasterKey {
|
|||
return keys
|
||||
}
|
||||
|
||||
func (k MasterKey) createStsSession(config aws.Config, sess *session.Session) (*session.Session, error) {
|
||||
func (key MasterKey) createStsSession(config aws.Config, sess *session.Session) (*session.Session, error) {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -101,7 +109,7 @@ func (k MasterKey) createStsSession(config aws.Config, sess *session.Session) (*
|
|||
stsService := sts.New(sess)
|
||||
name := "sops@" + hostname
|
||||
out, err := stsService.AssumeRole(&sts.AssumeRoleInput{
|
||||
RoleArn: &k.Role, RoleSessionName: &name})
|
||||
RoleArn: &key.Role, RoleSessionName: &name})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -114,30 +122,31 @@ func (k MasterKey) createStsSession(config aws.Config, sess *session.Session) (*
|
|||
return sess, nil
|
||||
}
|
||||
|
||||
func (k MasterKey) createSession() (*session.Session, error) {
|
||||
func (key MasterKey) createSession() (*session.Session, error) {
|
||||
re := regexp.MustCompile(`^arn:aws:kms:(.+):([0-9]+):key/(.+)$`)
|
||||
matches := re.FindStringSubmatch(k.Arn)
|
||||
matches := re.FindStringSubmatch(key.Arn)
|
||||
if matches == nil {
|
||||
return nil, fmt.Errorf("No valid ARN found in %s", k.Arn)
|
||||
return nil, fmt.Errorf("No valid ARN found in %s", key.Arn)
|
||||
}
|
||||
config := aws.Config{Region: aws.String(matches[1])}
|
||||
sess, err := session.NewSession(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if k.Role != "" {
|
||||
return k.createStsSession(config, sess)
|
||||
if key.Role != "" {
|
||||
return key.createStsSession(config, sess)
|
||||
}
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
func (k MasterKey) ToMap() map[string]string {
|
||||
// ToMap converts the MasterKey to a map for serialization purposes
|
||||
func (key MasterKey) ToMap() map[string]string {
|
||||
out := make(map[string]string)
|
||||
out["arn"] = k.Arn
|
||||
if k.Role != "" {
|
||||
out["role"] = k.Role
|
||||
out["arn"] = key.Arn
|
||||
if key.Role != "" {
|
||||
out["role"] = key.Role
|
||||
}
|
||||
out["created_at"] = k.CreationDate.UTC().Format(time.RFC3339)
|
||||
out["enc"] = k.EncryptedKey
|
||||
out["created_at"] = key.CreationDate.UTC().Format(time.RFC3339)
|
||||
out["enc"] = key.EncryptedKey
|
||||
return out
|
||||
}
|
||||
|
|
|
@ -131,8 +131,6 @@ func main() {
|
|||
return decrypt(c, file, fileBytes, output)
|
||||
} else if c.Bool("rotate") {
|
||||
return rotate(c, file, fileBytes, output)
|
||||
} else {
|
||||
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -16,12 +16,14 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// MasterKey is a PGP key used to securely store sops' data key by encrypting it and decrypting it
|
||||
type MasterKey struct {
|
||||
Fingerprint string
|
||||
EncryptedKey string
|
||||
CreationDate time.Time
|
||||
}
|
||||
|
||||
// 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()
|
||||
if err != nil {
|
||||
|
@ -61,6 +63,7 @@ func (key *MasterKey) Encrypt(dataKey []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// EncryptIfNeeded encrypts the data key with PGP only if it's needed, that is, if it hasn't been encrypted already
|
||||
func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error {
|
||||
if key.EncryptedKey == "" {
|
||||
return key.Encrypt(dataKey)
|
||||
|
@ -68,6 +71,7 @@ func (key *MasterKey) EncryptIfNeeded(dataKey []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Decrypt uses PGP to obtain the data key from the EncryptedKey store in the MasterKey and returns it
|
||||
func (key *MasterKey) Decrypt() ([]byte, error) {
|
||||
ring, err := key.secRing()
|
||||
if err != nil {
|
||||
|
@ -87,10 +91,12 @@ func (key *MasterKey) Decrypt() ([]byte, error) {
|
|||
return nil, fmt.Errorf("The key could not be decrypted with any of the GPG entries")
|
||||
}
|
||||
|
||||
// NeedsRotation returns whether the data key needs to be rotated or not
|
||||
func (key *MasterKey) NeedsRotation() bool {
|
||||
return time.Since(key.CreationDate).Hours() > 24*30*6
|
||||
}
|
||||
|
||||
// ToString returns the string representation of the key, i.e. its fingerprint
|
||||
func (key *MasterKey) ToString() string {
|
||||
return key.Fingerprint
|
||||
}
|
||||
|
@ -107,6 +113,7 @@ func (key *MasterKey) gpgHome() string {
|
|||
return dir
|
||||
}
|
||||
|
||||
// NewMasterKeyFromFingerprint takes a PGP fingerprint and returns a new MasterKey with that fingerprint
|
||||
func NewMasterKeyFromFingerprint(fingerprint string) MasterKey {
|
||||
return MasterKey{
|
||||
Fingerprint: strings.Replace(fingerprint, " ", "", -1),
|
||||
|
@ -114,6 +121,7 @@ func NewMasterKeyFromFingerprint(fingerprint string) MasterKey {
|
|||
}
|
||||
}
|
||||
|
||||
// MasterKeysFromFingerprintString takes a comma separated list of PGP fingerprints and returns a slice of new MasterKeys with those fingerprints
|
||||
func MasterKeysFromFingerprintString(fingerprint string) []MasterKey {
|
||||
var keys []MasterKey
|
||||
if fingerprint == "" {
|
||||
|
@ -191,6 +199,7 @@ func (key *MasterKey) passphrasePrompt(keys []openpgp.Key, symmetric bool) ([]by
|
|||
return nil, fmt.Errorf("No key to unlock")
|
||||
}
|
||||
|
||||
// ToMap converts the MasterKey into a map for serialization purposes
|
||||
func (key MasterKey) ToMap() map[string]string {
|
||||
out := make(map[string]string)
|
||||
out["fp"] = key.Fingerprint
|
||||
|
|
68
sops.go
68
sops.go
|
@ -11,27 +11,32 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// DefaultUnencryptedSuffix is the default suffix a TreeItem key has to end with for sops to leave its Value unencrypted
|
||||
const DefaultUnencryptedSuffix = "_unencrypted"
|
||||
|
||||
type Error string
|
||||
type sopsError string
|
||||
|
||||
func (e Error) Error() string { return string(e) }
|
||||
func (e sopsError) Error() string { return string(e) }
|
||||
|
||||
const MacMismatch = Error("MAC mismatch")
|
||||
// MacMismatch occurs when the computed MAC does not match the expected ones
|
||||
const MacMismatch = sopsError("MAC mismatch")
|
||||
|
||||
// TreeItem is an item inside sops's tree
|
||||
type TreeItem struct {
|
||||
Key string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
// TreeBranch is a branch inside sops's tree. It is a slice of TreeItems and is therefore ordered
|
||||
type TreeBranch []TreeItem
|
||||
|
||||
// Tree is the data structure used by sops to represent documents internally
|
||||
type Tree struct {
|
||||
Branch TreeBranch
|
||||
Metadata Metadata
|
||||
}
|
||||
|
||||
func (tree TreeBranch) WalkValue(in interface{}, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) (interface{}, error) {
|
||||
func (tree TreeBranch) walkValue(in interface{}, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) (interface{}, error) {
|
||||
switch in := in.(type) {
|
||||
case string:
|
||||
return onLeaves(in, path)
|
||||
|
@ -40,17 +45,17 @@ func (tree TreeBranch) WalkValue(in interface{}, path []string, onLeaves func(in
|
|||
case bool:
|
||||
return onLeaves(in, path)
|
||||
case TreeBranch:
|
||||
return tree.WalkBranch(in, path, onLeaves)
|
||||
return tree.walkBranch(in, path, onLeaves)
|
||||
case []interface{}:
|
||||
return tree.WalkSlice(in, path, onLeaves)
|
||||
return tree.walkSlice(in, path, onLeaves)
|
||||
default:
|
||||
return nil, fmt.Errorf("Cannot walk value, unknown type: %T", in)
|
||||
}
|
||||
}
|
||||
|
||||
func (tree TreeBranch) WalkSlice(in []interface{}, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) ([]interface{}, error) {
|
||||
func (tree TreeBranch) walkSlice(in []interface{}, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) ([]interface{}, error) {
|
||||
for i, v := range in {
|
||||
newV, err := tree.WalkValue(v, path, onLeaves)
|
||||
newV, err := tree.walkValue(v, path, onLeaves)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -59,9 +64,9 @@ func (tree TreeBranch) WalkSlice(in []interface{}, path []string, onLeaves func(
|
|||
return in, nil
|
||||
}
|
||||
|
||||
func (tree TreeBranch) WalkBranch(in TreeBranch, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) (TreeBranch, error) {
|
||||
func (tree TreeBranch) walkBranch(in TreeBranch, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) (TreeBranch, error) {
|
||||
for i, item := range in {
|
||||
newV, err := tree.WalkValue(item.Value, append(path, item.Key), onLeaves)
|
||||
newV, err := tree.walkValue(item.Value, append(path, item.Key), onLeaves)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -70,9 +75,10 @@ func (tree TreeBranch) WalkBranch(in TreeBranch, path []string, onLeaves func(in
|
|||
return in, nil
|
||||
}
|
||||
|
||||
// Encrypt walks over the tree and encrypts all values, except those whose key ends with the UnencryptedSuffix specified on the Metadata struct. If encryption is successful, it returns the MAC for the encrypted tree.
|
||||
func (tree Tree) Encrypt(key []byte) (string, error) {
|
||||
hash := sha512.New()
|
||||
_, err := tree.Branch.WalkBranch(tree.Branch, make([]string, 0), func(in interface{}, path []string) (interface{}, error) {
|
||||
_, err := tree.Branch.walkBranch(tree.Branch, make([]string, 0), func(in interface{}, path []string) (interface{}, error) {
|
||||
bytes, err := toBytes(in)
|
||||
if !strings.HasSuffix(path[len(path)-1], tree.Metadata.UnencryptedSuffix) {
|
||||
var err error
|
||||
|
@ -93,9 +99,10 @@ func (tree Tree) Encrypt(key []byte) (string, error) {
|
|||
return fmt.Sprintf("%X", hash.Sum(nil)), nil
|
||||
}
|
||||
|
||||
// Decrypt walks over the tree and decrypts all values, except those whose key ends with the UnencryptedSuffix specified on the Metadata struct. If decryption is successful, it returns the MAC for the decrypted tree.
|
||||
func (tree Tree) Decrypt(key []byte) (string, error) {
|
||||
hash := sha512.New()
|
||||
_, err := tree.Branch.WalkBranch(tree.Branch, make([]string, 0), func(in interface{}, path []string) (interface{}, error) {
|
||||
_, err := tree.Branch.walkBranch(tree.Branch, make([]string, 0), func(in interface{}, path []string) (interface{}, error) {
|
||||
var v interface{}
|
||||
if !strings.HasSuffix(path[len(path)-1], tree.Metadata.UnencryptedSuffix) {
|
||||
var err error
|
||||
|
@ -120,6 +127,7 @@ func (tree Tree) Decrypt(key []byte) (string, error) {
|
|||
|
||||
}
|
||||
|
||||
// Metadata holds information about a file encrypted by sops
|
||||
type Metadata struct {
|
||||
LastModified time.Time
|
||||
UnencryptedSuffix string
|
||||
|
@ -128,11 +136,13 @@ type Metadata struct {
|
|||
KeySources []KeySource
|
||||
}
|
||||
|
||||
// KeySource is a collection of MasterKeys with a Name.
|
||||
type KeySource struct {
|
||||
Name string
|
||||
Keys []MasterKey
|
||||
}
|
||||
|
||||
// MasterKey provides a way of securing the key used to encrypt the Tree by encrypting and decrypting said key.
|
||||
type MasterKey interface {
|
||||
Encrypt(dataKey []byte) error
|
||||
EncryptIfNeeded(dataKey []byte) error
|
||||
|
@ -142,6 +152,7 @@ type MasterKey interface {
|
|||
ToMap() map[string]string
|
||||
}
|
||||
|
||||
// Store provides a way to load and save the sops tree along with metadata
|
||||
type Store interface {
|
||||
Load(in string) (TreeBranch, error)
|
||||
LoadMetadata(in string) (Metadata, error)
|
||||
|
@ -149,6 +160,7 @@ type Store interface {
|
|||
DumpWithMetadata(TreeBranch, Metadata) (string, error)
|
||||
}
|
||||
|
||||
// MasterKeyCount returns the number of master keys available
|
||||
func (m *Metadata) MasterKeyCount() int {
|
||||
count := 0
|
||||
for _, ks := range m.KeySources {
|
||||
|
@ -156,6 +168,8 @@ func (m *Metadata) MasterKeyCount() int {
|
|||
}
|
||||
return count
|
||||
}
|
||||
|
||||
// RemoveMasterKeys removes all of the provided keys from the metadata's KeySources, if they exist there.
|
||||
func (m *Metadata) RemoveMasterKeys(keys []MasterKey) {
|
||||
for j, ks := range m.KeySources {
|
||||
for i, k := range ks.Keys {
|
||||
|
@ -169,6 +183,7 @@ func (m *Metadata) RemoveMasterKeys(keys []MasterKey) {
|
|||
}
|
||||
}
|
||||
|
||||
// UpdateMasterKeys encrypts the data key with all master keys if it's needed
|
||||
func (m *Metadata) UpdateMasterKeys(dataKey []byte) {
|
||||
for _, ks := range m.KeySources {
|
||||
for _, k := range ks.Keys {
|
||||
|
@ -180,8 +195,9 @@ func (m *Metadata) UpdateMasterKeys(dataKey []byte) {
|
|||
}
|
||||
}
|
||||
|
||||
func (metadata *Metadata) AddPGPMasterKeys(pgpFps string) {
|
||||
for i, ks := range metadata.KeySources {
|
||||
// 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 {
|
||||
if ks.Name == "pgp" {
|
||||
var keys []MasterKey
|
||||
for _, k := range pgp.MasterKeysFromFingerprintString(pgpFps) {
|
||||
|
@ -189,48 +205,52 @@ func (metadata *Metadata) AddPGPMasterKeys(pgpFps string) {
|
|||
fmt.Println("Keys to add:", keys)
|
||||
}
|
||||
ks.Keys = append(ks.Keys, keys...)
|
||||
metadata.KeySources[i] = ks
|
||||
m.KeySources[i] = ks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (metadata *Metadata) AddKMSMasterKeys(kmsArns string) {
|
||||
for i, ks := range metadata.KeySources {
|
||||
// AddKMSMasterKeys parses the input comma separated string of AWS KMS ARNs, generates a KMS MasterKey for each ARN, and then adds the keys to the KMS KeySource
|
||||
func (m *Metadata) AddKMSMasterKeys(kmsArns string) {
|
||||
for i, ks := range m.KeySources {
|
||||
if ks.Name == "kms" {
|
||||
var keys []MasterKey
|
||||
for _, k := range kms.MasterKeysFromArnString(kmsArns) {
|
||||
keys = append(keys, &k)
|
||||
}
|
||||
ks.Keys = append(ks.Keys, keys...)
|
||||
metadata.KeySources[i] = ks
|
||||
m.KeySources[i] = ks
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (metadata *Metadata) RemovePGPMasterKeys(pgpFps string) {
|
||||
// RemovePGPMasterKeys takes a comma separated string of PGP fingerprints and removes the keys corresponding to those fingerprints from the metadata's KeySources
|
||||
func (m *Metadata) RemovePGPMasterKeys(pgpFps string) {
|
||||
var keys []MasterKey
|
||||
for _, k := range pgp.MasterKeysFromFingerprintString(pgpFps) {
|
||||
keys = append(keys, &k)
|
||||
}
|
||||
metadata.RemoveMasterKeys(keys)
|
||||
m.RemoveMasterKeys(keys)
|
||||
}
|
||||
|
||||
func (metadata *Metadata) RemoveKMSMasterKeys(arns string) {
|
||||
// RemoveKMSMasterKeys takes a comma separated string of AWS KMS ARNs and removes the keys corresponding to those ARNs from the metadata's KeySources
|
||||
func (m *Metadata) RemoveKMSMasterKeys(arns string) {
|
||||
var keys []MasterKey
|
||||
for _, k := range kms.MasterKeysFromArnString(arns) {
|
||||
keys = append(keys, &k)
|
||||
}
|
||||
metadata.RemoveMasterKeys(keys)
|
||||
m.RemoveMasterKeys(keys)
|
||||
}
|
||||
|
||||
// ToMap converts the Metadata to a map for serialization purposes
|
||||
func (m *Metadata) ToMap() map[string]interface{} {
|
||||
out := make(map[string]interface{})
|
||||
out["lastmodified"] = m.LastModified.Format("2006-01-02T15:04:05Z")
|
||||
out["lastmodified"] = m.LastModified.Format(time.RFC3339)
|
||||
out["unencrypted_suffix"] = m.UnencryptedSuffix
|
||||
out["mac"] = m.MessageAuthenticationCode
|
||||
out["version"] = m.Version
|
||||
for _, ks := range m.KeySources {
|
||||
keys := make([]map[string]string, 0)
|
||||
var keys []map[string]string
|
||||
for _, k := range ks.Keys {
|
||||
keys = append(keys, k.ToMap())
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
// Store handles storage of YAML data
|
||||
type Store struct {
|
||||
}
|
||||
|
||||
|
@ -24,6 +25,7 @@ func (store Store) mapSliceToTreeBranch(in yaml.MapSlice) sops.TreeBranch {
|
|||
return branch
|
||||
}
|
||||
|
||||
// Load takes a YAML document as input and unmarshals it into a sops tree, returning the tree
|
||||
func (store Store) Load(in string) (sops.TreeBranch, error) {
|
||||
var data yaml.MapSlice
|
||||
if err := yaml.Unmarshal([]byte(in), &data); err != nil {
|
||||
|
@ -88,6 +90,7 @@ func (store Store) treeBranchToYamlMap(in sops.TreeBranch) yaml.MapSlice {
|
|||
return branch
|
||||
}
|
||||
|
||||
// Dump takes a sops tree branch and marshals it into a yaml document
|
||||
func (store Store) Dump(tree sops.TreeBranch) (string, error) {
|
||||
yamlMap := store.treeBranchToYamlMap(tree)
|
||||
out, err := yaml.Marshal(yamlMap)
|
||||
|
@ -97,6 +100,7 @@ func (store Store) Dump(tree sops.TreeBranch) (string, error) {
|
|||
return string(out), nil
|
||||
}
|
||||
|
||||
// DumpWithMetadata takes a sops tree branch and metadata and marshals them into a yaml document
|
||||
func (store Store) DumpWithMetadata(tree sops.TreeBranch, metadata sops.Metadata) (string, error) {
|
||||
yamlMap := store.treeBranchToYamlMap(tree)
|
||||
yamlMap = append(yamlMap, yaml.MapItem{Key: "sops", Value: metadata.ToMap()})
|
||||
|
@ -107,6 +111,7 @@ func (store Store) DumpWithMetadata(tree sops.TreeBranch, metadata sops.Metadata
|
|||
return string(out), nil
|
||||
}
|
||||
|
||||
// LoadMetadata takes a yaml document as a string and extracts sops' metadata from it
|
||||
func (store *Store) LoadMetadata(in string) (sops.Metadata, error) {
|
||||
var metadata sops.Metadata
|
||||
var ok bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче