зеркало из https://github.com/getsops/sops.git
Fix golint errors
This commit is contained in:
Родитель
d1637e0da7
Коммит
93570b20d7
2
Makefile
2
Makefile
|
@ -28,7 +28,7 @@ test:
|
|||
$(GO) test -coverprofile=coverage_tmp.txt -covermode=atomic $(PROJECT) && cat coverage_tmp.txt >> coverage.txt
|
||||
$(GO) test $(PROJECT)/aes -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
|
||||
$(GO) test $(PROJECT)/cmd/sops -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
|
||||
$(GO) test $(PROJECT)/yaml -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
|
||||
$(GO) test $(PROJECT)/config -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
|
||||
$(GO) test $(PROJECT)/stores/yaml -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
|
||||
$(GO) test $(PROJECT)/stores/json -coverprofile=coverage_tmp.txt -covermode=atomic && cat coverage_tmp.txt >> coverage.txt
|
||||
gpg --import pgp/sops_functional_tests_key.asc 2>&1 1>/dev/null || exit 0
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
// Package codes the exit statuses returned by the sops binary
|
||||
package codes
|
||||
|
||||
// Exit statuses returned by the binary
|
||||
const (
|
||||
CouldNotReadInputFile int = 2
|
||||
CouldNotWriteOutputFile int = 3
|
||||
|
|
|
@ -12,16 +12,23 @@ import (
|
|||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
// DecryptTreeOpts are the options needed to decrypt a tree
|
||||
type DecryptTreeOpts struct {
|
||||
Tree *sops.Tree
|
||||
Stash map[string][]interface{}
|
||||
// Tree is the tree to be decrypted
|
||||
Tree *sops.Tree
|
||||
// Stash is a map to save information between encryption-decryption round-trips, such as IVs
|
||||
Stash map[string][]interface{}
|
||||
// KeyServices are the key services to be used for decryption of the data key
|
||||
KeyServices []keyservice.KeyServiceClient
|
||||
IgnoreMac bool
|
||||
Cipher sops.DataKeyCipher
|
||||
// IgnoreMac is whether or not to ignore the Message Authentication Code included in the SOPS tree
|
||||
IgnoreMac bool
|
||||
// Cipher is the cryptographic cipher to use to decrypt the values inside the tree
|
||||
Cipher sops.DataKeyCipher
|
||||
}
|
||||
|
||||
func DecryptTree(opts DecryptTreeOpts) ([]byte, error) {
|
||||
dataKey, err := opts.Tree.Metadata.GetDataKeyWithKeyServices(opts.KeyServices)
|
||||
// DecryptTree decrypts the tree passed in through the DecryptTreeOpts and additionally returns the decrypted data key
|
||||
func DecryptTree(opts DecryptTreeOpts) (dataKey []byte, err error) {
|
||||
dataKey, err = opts.Tree.Metadata.GetDataKeyWithKeyServices(opts.KeyServices)
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(err.Error(), codes.CouldNotRetrieveKey)
|
||||
}
|
||||
|
@ -42,13 +49,19 @@ func DecryptTree(opts DecryptTreeOpts) ([]byte, error) {
|
|||
return dataKey, nil
|
||||
}
|
||||
|
||||
// EncryptTreeOpts are the options needed to encrypt a tree
|
||||
type EncryptTreeOpts struct {
|
||||
Tree *sops.Tree
|
||||
Stash map[string][]interface{}
|
||||
Cipher sops.DataKeyCipher
|
||||
// Tree is the tree to be encrypted
|
||||
Tree *sops.Tree
|
||||
// Stash is a map to save information between encryption-decryption round-trips, such as IVs
|
||||
Stash map[string][]interface{}
|
||||
// Cipher is the cryptographic cipher to use to encrypt the values inside the tree
|
||||
Cipher sops.DataKeyCipher
|
||||
// DataKey is the key the cipher should use to encrypt the values inside the tree
|
||||
DataKey []byte
|
||||
}
|
||||
|
||||
// EncryptTree encrypts the tree passed in through the EncryptTreeOpts
|
||||
func EncryptTree(opts EncryptTreeOpts) error {
|
||||
mac, err := opts.Tree.Encrypt(opts.DataKey, opts.Cipher, opts.Stash)
|
||||
if err != nil {
|
||||
|
@ -63,6 +76,7 @@ func EncryptTree(opts EncryptTreeOpts) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// LoadEncryptedFile loads an encrypted SOPS file, returning a SOPS tree
|
||||
func LoadEncryptedFile(inputStore sops.Store, inputPath string) (*sops.Tree, error) {
|
||||
fileBytes, err := ioutil.ReadFile(inputPath)
|
||||
if err != nil {
|
||||
|
|
|
@ -20,7 +20,7 @@ type decryptOpts struct {
|
|||
KeyServices []keyservice.KeyServiceClient
|
||||
}
|
||||
|
||||
func Decrypt(opts decryptOpts) (decryptedFile []byte, err error) {
|
||||
func decrypt(opts decryptOpts) (decryptedFile []byte, err error) {
|
||||
tree, err := common.LoadEncryptedFile(opts.InputStore, opts.InputPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -38,7 +38,7 @@ func Decrypt(opts decryptOpts) (decryptedFile []byte, err error) {
|
|||
}
|
||||
|
||||
if len(opts.Extract) > 0 {
|
||||
return Extract(tree, opts.Extract, opts.OutputStore)
|
||||
return extract(tree, opts.Extract, opts.OutputStore)
|
||||
}
|
||||
decryptedFile, err = opts.OutputStore.Marshal(tree.Branch)
|
||||
if err != nil {
|
||||
|
@ -47,7 +47,7 @@ func Decrypt(opts decryptOpts) (decryptedFile []byte, err error) {
|
|||
return decryptedFile, err
|
||||
}
|
||||
|
||||
func Extract(tree *sops.Tree, path []interface{}, outputStore sops.Store) (output []byte, err error) {
|
||||
func extract(tree *sops.Tree, path []interface{}, outputStore sops.Store) (output []byte, err error) {
|
||||
v, err := tree.Branch.Truncate(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error truncating tree: %s", err)
|
||||
|
@ -59,11 +59,10 @@ func Extract(tree *sops.Tree, path []interface{}, outputStore sops.Store) (outpu
|
|||
return nil, cli.NewExitError(fmt.Sprintf("Error dumping file: %s", err), codes.ErrorDumpingTree)
|
||||
}
|
||||
return decrypted, err
|
||||
} else {
|
||||
bytes, err := outputStore.MarshalValue(v)
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(fmt.Sprintf("Error dumping tree: %s", err), codes.ErrorDumpingTree)
|
||||
}
|
||||
return bytes, nil
|
||||
}
|
||||
bytes, err := outputStore.MarshalValue(v)
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(fmt.Sprintf("Error dumping tree: %s", err), codes.ErrorDumpingTree)
|
||||
}
|
||||
return bytes, nil
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ type runEditorUntilOkOpts struct {
|
|||
Tree *sops.Tree
|
||||
}
|
||||
|
||||
func EditExample(opts editExampleOpts) ([]byte, error) {
|
||||
func editExample(opts editExampleOpts) ([]byte, error) {
|
||||
// Load the example file
|
||||
var fileBytes []byte
|
||||
if _, ok := opts.InputStore.(*json.BinaryStore); ok {
|
||||
|
@ -109,10 +109,10 @@ func EditExample(opts editExampleOpts) ([]byte, error) {
|
|||
}
|
||||
stash := make(map[string][]interface{})
|
||||
|
||||
return edit(opts.editOpts, &tree, dataKey, stash)
|
||||
return editTree(opts.editOpts, &tree, dataKey, stash)
|
||||
}
|
||||
|
||||
func Edit(opts editOpts) ([]byte, error) {
|
||||
func edit(opts editOpts) ([]byte, error) {
|
||||
// Load the file
|
||||
tree, err := common.LoadEncryptedFile(opts.InputStore, opts.InputPath)
|
||||
if err != nil {
|
||||
|
@ -127,10 +127,10 @@ func Edit(opts editOpts) ([]byte, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return edit(opts, tree, dataKey, stash)
|
||||
return editTree(opts, tree, dataKey, stash)
|
||||
}
|
||||
|
||||
func edit(opts editOpts, tree *sops.Tree, dataKey []byte, stash map[string][]interface{}) ([]byte, error) {
|
||||
func editTree(opts editOpts, tree *sops.Tree, dataKey []byte, stash map[string][]interface{}) ([]byte, error) {
|
||||
// Create temporary file for editing
|
||||
tmpdir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
|
|
|
@ -23,7 +23,7 @@ type encryptOpts struct {
|
|||
GroupQuorum int
|
||||
}
|
||||
|
||||
func Encrypt(opts encryptOpts) (encryptedFile []byte, err error) {
|
||||
func encrypt(opts encryptOpts) (encryptedFile []byte, err error) {
|
||||
// Load the file
|
||||
fileBytes, err := ioutil.ReadFile(opts.InputPath)
|
||||
if err != nil {
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
"go.mozilla.org/sops/pgp"
|
||||
"go.mozilla.org/sops/stores/json"
|
||||
yamlstores "go.mozilla.org/sops/stores/yaml"
|
||||
"go.mozilla.org/sops/yaml"
|
||||
"go.mozilla.org/sops/config"
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
)
|
||||
|
||||
|
@ -306,7 +306,7 @@ func main() {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err = Encrypt(encryptOpts{
|
||||
output, err = encrypt(encryptOpts{
|
||||
OutputStore: outputStore,
|
||||
InputStore: inputStore,
|
||||
InputPath: fileName,
|
||||
|
@ -326,7 +326,7 @@ func main() {
|
|||
if err != nil {
|
||||
return cli.NewExitError(fmt.Errorf("error parsing --extract path: %s", err), codes.InvalidTreePathFormat)
|
||||
}
|
||||
output, err = Decrypt(decryptOpts{
|
||||
output, err = decrypt(decryptOpts{
|
||||
OutputStore: outputStore,
|
||||
InputStore: inputStore,
|
||||
InputPath: fileName,
|
||||
|
@ -356,7 +356,7 @@ func main() {
|
|||
for _, k := range pgp.MasterKeysFromFingerprintString(c.String("add-pgp")) {
|
||||
rmMasterKeys = append(rmMasterKeys, k)
|
||||
}
|
||||
output, err = Rotate(rotateOpts{
|
||||
output, err = rotate(rotateOpts{
|
||||
OutputStore: outputStore,
|
||||
InputStore: inputStore,
|
||||
InputPath: fileName,
|
||||
|
@ -376,7 +376,7 @@ func main() {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err = Set(setOpts{
|
||||
output, err = set(setOpts{
|
||||
OutputStore: outputStore,
|
||||
InputStore: inputStore,
|
||||
InputPath: fileName,
|
||||
|
@ -405,14 +405,14 @@ func main() {
|
|||
ShowMasterKeys: c.Bool("show-master-keys"),
|
||||
}
|
||||
if fileExists {
|
||||
output, err = Edit(opts)
|
||||
output, err = edit(opts)
|
||||
} else {
|
||||
// File doesn't exist, edit the example file instead
|
||||
keyGroups, err := keyGroups(c, fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
output, err = EditExample(editExampleOpts{
|
||||
output, err = editExample(editExampleOpts{
|
||||
editOpts: opts,
|
||||
UnencryptedSuffix: c.String("unencrypted-suffix"),
|
||||
KeyGroups: keyGroups,
|
||||
|
@ -557,7 +557,7 @@ func keyGroups(c *cli.Context, file string) ([]sops.KeyGroup, error) {
|
|||
return nil, cli.NewExitError(fmt.Sprintf("Error loading config file: %s", err), codes.ErrorReadingConfig)
|
||||
}
|
||||
}
|
||||
groups, err := yaml.KeyGroupsForFile(file, confBytes, kmsEncryptionContext)
|
||||
groups, err := config.KeyGroupsForFile(file, confBytes, kmsEncryptionContext)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ type rotateOpts struct {
|
|||
KeyServices []keyservice.KeyServiceClient
|
||||
}
|
||||
|
||||
func Rotate(opts rotateOpts) ([]byte, error) {
|
||||
func rotate(opts rotateOpts) ([]byte, error) {
|
||||
tree, err := common.LoadEncryptedFile(opts.InputStore, opts.InputPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -21,7 +21,7 @@ type setOpts struct {
|
|||
KeyServices []keyservice.KeyServiceClient
|
||||
}
|
||||
|
||||
func Set(opts setOpts) ([]byte, error) {
|
||||
func set(opts setOpts) ([]byte, error) {
|
||||
// Load the file
|
||||
// TODO: Issue #173: if the file does not exist, create it with the contents passed in as opts.Value
|
||||
tree, err := common.LoadEncryptedFile(opts.InputStore, opts.InputPath)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"go.mozilla.org/sops/keyservice"
|
||||
)
|
||||
|
||||
// AddOpts are the options for adding a key group to a SOPS file
|
||||
type AddOpts struct {
|
||||
InputPath string
|
||||
InputStore sops.Store
|
||||
|
@ -18,6 +19,7 @@ type AddOpts struct {
|
|||
KeyServices []keyservice.KeyServiceClient
|
||||
}
|
||||
|
||||
// Add adds a key group to a SOPS file
|
||||
func Add(opts AddOpts) error {
|
||||
tree, err := common.LoadEncryptedFile(opts.InputStore, opts.InputPath)
|
||||
if err != nil {
|
||||
|
@ -37,7 +39,7 @@ func Add(opts AddOpts) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var outputFile *os.File = os.Stdout
|
||||
var outputFile = os.Stdout
|
||||
if opts.InPlace {
|
||||
var err error
|
||||
outputFile, err = os.Create(opts.InputPath)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"go.mozilla.org/sops/keyservice"
|
||||
)
|
||||
|
||||
// DeleteOpts are the options for deleting a key group from a SOPS file
|
||||
type DeleteOpts struct {
|
||||
InputPath string
|
||||
InputStore sops.Store
|
||||
|
@ -25,6 +26,7 @@ func min(a, b int) int {
|
|||
return a
|
||||
}
|
||||
|
||||
// Delete deletes a key group from a SOPS file
|
||||
func Delete(opts DeleteOpts) error {
|
||||
tree, err := common.LoadEncryptedFile(opts.InputStore, opts.InputPath)
|
||||
if err != nil {
|
||||
|
@ -47,7 +49,7 @@ func Delete(opts DeleteOpts) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var outputFile *os.File = os.Stdout
|
||||
var outputFile = os.Stdout
|
||||
if opts.InPlace {
|
||||
var err error
|
||||
outputFile, err = os.Create(opts.InputPath)
|
||||
|
|
|
@ -12,11 +12,13 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// Opts are the options the key service server can take
|
||||
type Opts struct {
|
||||
Network string
|
||||
Address string
|
||||
}
|
||||
|
||||
// Run runs a SOPS key service server
|
||||
func Run(opts Opts) error {
|
||||
lis, err := net.Listen(opts.Network, opts.Address)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package yaml //import "go.mozilla.org/sops/yaml"
|
||||
package config //import "go.mozilla.org/sops/config"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -71,6 +71,8 @@ func (f *configFile) load(bytes []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// KeyGroupsForFile returns the key groups that should be use for a given file, based on the file's path and the
|
||||
// configuration
|
||||
func KeyGroupsForFile(filepath string, confBytes []byte, kmsEncryptionContext map[string]*string) ([]sops.KeyGroup, error) {
|
||||
var err error
|
||||
if confBytes == nil {
|
|
@ -1,4 +1,4 @@
|
|||
package yaml
|
||||
package config
|
||||
|
||||
import (
|
||||
"os"
|
|
@ -6,19 +6,25 @@ import (
|
|||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// LocalClient is a key service client that performs all operations locally
|
||||
type LocalClient struct {
|
||||
Server Server
|
||||
}
|
||||
|
||||
// NewLocalClient creates a new local client
|
||||
func NewLocalClient() LocalClient {
|
||||
return LocalClient{Server{}}
|
||||
}
|
||||
|
||||
// Decrypt processes a decrypt request locally
|
||||
// See keyservice/server.go for more details
|
||||
func (c LocalClient) Decrypt(ctx context.Context,
|
||||
req *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error) {
|
||||
return c.Server.Decrypt(ctx, req)
|
||||
}
|
||||
|
||||
// Encrypt processes an encrypt request locally
|
||||
// See keyservice/server.go for more details
|
||||
func (c LocalClient) Encrypt(ctx context.Context,
|
||||
req *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error) {
|
||||
return c.Server.Encrypt(ctx, req)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"go.mozilla.org/sops/pgp"
|
||||
)
|
||||
|
||||
// KeyFromMasterKey converts a SOPS internal MasterKey to an RPC Key that can be serialized with Protocol Buffers
|
||||
func KeyFromMasterKey(mk keys.MasterKey) Key {
|
||||
switch mk := mk.(type) {
|
||||
case *pgp.MasterKey:
|
||||
|
|
|
@ -6,8 +6,10 @@ import (
|
|||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// Server is a key service server that uses SOPS MasterKeys to fulfill requests
|
||||
type Server struct{}
|
||||
|
||||
func (ks *Server) encryptWithPgp(key *PgpKey, plaintext []byte) ([]byte, error) {
|
||||
|
@ -58,6 +60,8 @@ func (ks *Server) decryptWithKms(key *KmsKey, ciphertext []byte) ([]byte, error)
|
|||
return []byte(plaintext), err
|
||||
}
|
||||
|
||||
// Encrypt takes an encrypt request and encrypts the provided plaintext with the provided key, returning the encrypted
|
||||
// result
|
||||
func (ks Server) Encrypt(ctx context.Context,
|
||||
req *EncryptRequest) (*EncryptResponse, error) {
|
||||
key := *req.Key
|
||||
|
@ -79,12 +83,14 @@ func (ks Server) Encrypt(ctx context.Context,
|
|||
Ciphertext: ciphertext,
|
||||
}, nil
|
||||
case nil:
|
||||
return nil, grpc.Errorf(codes.NotFound, "Must provide a key")
|
||||
return nil, status.Errorf(codes.NotFound, "Must provide a key")
|
||||
default:
|
||||
return nil, grpc.Errorf(codes.NotFound, "Unknown key type")
|
||||
return nil, status.Errorf(codes.NotFound, "Unknown key type")
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt takes a decrypt request and decrypts the provided ciphertext with the provided key, returning the decrypted
|
||||
// result
|
||||
func (ks Server) Decrypt(ctx context.Context,
|
||||
req *DecryptRequest) (*DecryptResponse, error) {
|
||||
key := *req.Key
|
||||
|
|
|
@ -33,10 +33,12 @@ type MasterKey struct {
|
|||
EncryptionContext map[string]*string
|
||||
}
|
||||
|
||||
// EncryptedDataKey returns the encrypted data key this master key holds
|
||||
func (key *MasterKey) EncryptedDataKey() []byte {
|
||||
return []byte(key.EncryptedKey)
|
||||
}
|
||||
|
||||
// SetEncryptedDataKey sets the encrypted data key for this master key
|
||||
func (key *MasterKey) SetEncryptedDataKey(enc []byte) {
|
||||
key.EncryptedKey = string(enc)
|
||||
}
|
||||
|
|
|
@ -28,10 +28,12 @@ type MasterKey struct {
|
|||
CreationDate time.Time
|
||||
}
|
||||
|
||||
// EncryptedDataKey returns the encrypted data key this master key holds
|
||||
func (key *MasterKey) EncryptedDataKey() []byte {
|
||||
return []byte(key.EncryptedKey)
|
||||
}
|
||||
|
||||
// SetEncryptedDataKey sets the encrypted data key for this master key
|
||||
func (key *MasterKey) SetEncryptedDataKey(enc []byte) {
|
||||
key.EncryptedKey = string(enc)
|
||||
}
|
||||
|
@ -77,7 +79,7 @@ func (key *MasterKey) encryptWithCryptoOpenPGP(dataKey []byte) error {
|
|||
fingerprints := key.fingerprintMap(ring)
|
||||
entity, ok := fingerprints[key.Fingerprint]
|
||||
if !ok {
|
||||
return fmt.Errorf("Key with fingerprint %s is not available in keyring.", key.Fingerprint)
|
||||
return fmt.Errorf("key with fingerprint %s is not available in keyring", key.Fingerprint)
|
||||
}
|
||||
encbuf := new(bytes.Buffer)
|
||||
armorbuf, err := armor.Encode(encbuf, "PGP MESSAGE", nil)
|
||||
|
|
36
sops.go
36
sops.go
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Package Sops manages JSON, YAML and BINARY documents to be encrypted or decrypted.
|
||||
Package sops manages JSON, YAML and BINARY documents to be encrypted or decrypted.
|
||||
|
||||
This package should not be used directly. Instead, Sops users should install the
|
||||
command line client via `go get -u go.mozilla.org/sops/cmd/sops`, or use the
|
||||
|
@ -112,9 +112,9 @@ type Tree struct {
|
|||
}
|
||||
|
||||
// Truncate truncates the tree to the path specified
|
||||
func (tree TreeBranch) Truncate(path []interface{}) (interface{}, error) {
|
||||
func (branch TreeBranch) Truncate(path []interface{}) (interface{}, error) {
|
||||
log.Printf("Truncating tree to %s", path)
|
||||
var current interface{} = tree
|
||||
var current interface{} = branch
|
||||
for _, component := range path {
|
||||
switch component := component.(type) {
|
||||
case string:
|
||||
|
@ -142,7 +142,7 @@ func (tree TreeBranch) Truncate(path []interface{}) (interface{}, error) {
|
|||
return current, nil
|
||||
}
|
||||
|
||||
func (tree TreeBranch) walkValue(in interface{}, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) (interface{}, error) {
|
||||
func (branch 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)
|
||||
|
@ -155,20 +155,20 @@ func (tree TreeBranch) walkValue(in interface{}, path []string, onLeaves func(in
|
|||
case float64:
|
||||
return onLeaves(in, path)
|
||||
case TreeBranch:
|
||||
return tree.walkBranch(in, path, onLeaves)
|
||||
return branch.walkBranch(in, path, onLeaves)
|
||||
case []interface{}:
|
||||
return tree.walkSlice(in, path, onLeaves)
|
||||
return branch.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 (branch TreeBranch) walkSlice(in []interface{}, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) ([]interface{}, error) {
|
||||
for i, v := range in {
|
||||
if _, ok := v.(Comment); ok {
|
||||
continue
|
||||
}
|
||||
newV, err := tree.walkValue(v, path, onLeaves)
|
||||
newV, err := branch.walkValue(v, path, onLeaves)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ 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 (branch TreeBranch) walkBranch(in TreeBranch, path []string, onLeaves func(in interface{}, path []string) (interface{}, error)) (TreeBranch, error) {
|
||||
for i, item := range in {
|
||||
if _, ok := item.Key.(Comment); ok {
|
||||
continue
|
||||
|
@ -187,7 +187,7 @@ func (tree TreeBranch) walkBranch(in TreeBranch, path []string, onLeaves func(in
|
|||
return nil, fmt.Errorf("Tree contains a non-string key (type %T): %s. Only string keys are"+
|
||||
"supported", item.Key, item.Key)
|
||||
}
|
||||
newV, err := tree.walkValue(item.Value, append(path, key), onLeaves)
|
||||
newV, err := branch.walkValue(item.Value, append(path, key), onLeaves)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ func (tree Tree) GenerateDataKey() ([]byte, []error) {
|
|||
return newKey, tree.Metadata.UpdateMasterKeys(newKey)
|
||||
}
|
||||
|
||||
// GenerateDataKey generates a new random data key and encrypts it with all MasterKeys.
|
||||
// GenerateDataKeyWithKeyServices generates a new random data key and encrypts it with all MasterKeys.
|
||||
func (tree *Tree) GenerateDataKeyWithKeyServices(svcs []keyservice.KeyServiceClient) ([]byte, []error) {
|
||||
newKey := make([]byte, 32)
|
||||
_, err := rand.Read(newKey)
|
||||
|
@ -306,6 +306,7 @@ type Metadata struct {
|
|||
DataKey []byte
|
||||
}
|
||||
|
||||
// KeyGroup is a slice of SOPS MasterKeys that all encrypt the same part of the data key
|
||||
type KeyGroup []keys.MasterKey
|
||||
|
||||
// Store provides a way to load and save the sops tree along with metadata
|
||||
|
@ -326,10 +327,11 @@ func (m *Metadata) MasterKeyCount() int {
|
|||
return count
|
||||
}
|
||||
|
||||
// UpdateMasterKeysWithKeyServices encrypts the data key with all master keys using the provided key services
|
||||
func (m *Metadata) UpdateMasterKeysWithKeyServices(dataKey []byte, svcs []keyservice.KeyServiceClient) (errs []error) {
|
||||
if len(svcs) == 0 {
|
||||
return []error{
|
||||
fmt.Errorf("No key services provided, cansnot update master keys."),
|
||||
fmt.Errorf("no key services provided, cannot update master keys"),
|
||||
}
|
||||
}
|
||||
var parts [][]byte
|
||||
|
@ -345,11 +347,11 @@ func (m *Metadata) UpdateMasterKeysWithKeyServices(dataKey []byte, svcs []keyser
|
|||
log.Printf("Multiple KeyGroups found, proceeding with Shamir with quorum %d", m.ShamirQuorum)
|
||||
parts, err = shamir.Split(dataKey, len(m.KeyGroups), m.ShamirQuorum)
|
||||
if err != nil {
|
||||
errs = append(errs, fmt.Errorf("Could not split data key into parts for Shamir: %s", err))
|
||||
errs = append(errs, fmt.Errorf("could not split data key into parts for Shamir: %s", err))
|
||||
return
|
||||
}
|
||||
if len(parts) != len(m.KeyGroups) {
|
||||
errs = append(errs, fmt.Errorf("Not enough parts obtained from Shamir. Need %d, got %d", len(m.KeyGroups), len(parts)))
|
||||
errs = append(errs, fmt.Errorf("not enough parts obtained from Shamir: need %d, got %d", len(m.KeyGroups), len(parts)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -365,7 +367,7 @@ func (m *Metadata) UpdateMasterKeysWithKeyServices(dataKey []byte, svcs []keyser
|
|||
Plaintext: part,
|
||||
})
|
||||
if err != nil {
|
||||
keyErrs = append(keyErrs, fmt.Errorf("Failed to encrypt new data key with master key %q: %v\n", key.ToString(), err))
|
||||
keyErrs = append(keyErrs, fmt.Errorf("failed to encrypt new data key with master key %q: %v", key.ToString(), err))
|
||||
continue
|
||||
}
|
||||
key.SetEncryptedDataKey(rsp.Ciphertext)
|
||||
|
@ -423,12 +425,12 @@ func (m Metadata) GetDataKeyWithKeyServices(svcs []keyservice.KeyServiceClient)
|
|||
var dataKey []byte
|
||||
if len(m.KeyGroups) > 1 {
|
||||
if len(parts) < m.ShamirQuorum {
|
||||
return nil, fmt.Errorf("Not enough parts to recover data key with Shamir. Need %d, have %d.", m.ShamirQuorum, len(parts))
|
||||
return nil, fmt.Errorf("not enough parts to recover data key with Shamir: need %d, have %d", m.ShamirQuorum, len(parts))
|
||||
}
|
||||
var err error
|
||||
dataKey, err = shamir.Combine(parts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Could not get data key from shamir parts: %s", err)
|
||||
return nil, fmt.Errorf("could not get data key from shamir parts: %s", err)
|
||||
}
|
||||
} else {
|
||||
if len(parts) != 1 {
|
||||
|
|
|
@ -10,12 +10,13 @@ import (
|
|||
"go.mozilla.org/sops/pgp"
|
||||
)
|
||||
|
||||
// SopsFile is a struct used by the stores as a helper unmarshal the SOPS metadata
|
||||
type SopsFile struct {
|
||||
Data interface{} `yaml:"data" json:"data"`
|
||||
Metadata Metadata `yaml:"sops" json:"sops"`
|
||||
}
|
||||
|
||||
// metadata is stored in SOPS encrypted files, and it contains the information necessary to decrypt the file.
|
||||
// Metadata is stored in SOPS encrypted files, and it contains the information necessary to decrypt the file.
|
||||
// This struct is just used for serialization, and SOPS uses another struct internally, sops.Metadata. It exists
|
||||
// in order to allow the binary format to stay backwards compatible over time, but at the same time allow the internal
|
||||
// representation SOPS uses to change over time.
|
||||
|
@ -49,6 +50,7 @@ type kmskey struct {
|
|||
EncryptedDataKey string `yaml:"enc" json:"enc"`
|
||||
}
|
||||
|
||||
// MetadataFromInternal converts an internal SOPS metadata representation to a representation appropriate for storage
|
||||
func MetadataFromInternal(sopsMetadata sops.Metadata) Metadata {
|
||||
var m Metadata
|
||||
m.LastModified = sopsMetadata.LastModified.Format(time.RFC3339)
|
||||
|
@ -101,6 +103,7 @@ func kmsKeysFromGroup(group sops.KeyGroup) (keys []kmskey) {
|
|||
return
|
||||
}
|
||||
|
||||
// ToInternal converts a storage-appropriate Metadata struct to a SOPS internal representation
|
||||
func (m *Metadata) ToInternal() (sops.Metadata, error) {
|
||||
lastModified, err := time.Parse(time.RFC3339, m.LastModified)
|
||||
if err != nil {
|
||||
|
|
|
@ -134,14 +134,14 @@ func (store Store) MarshalWithMetadata(tree sops.TreeBranch, metadata sops.Metad
|
|||
return out, nil
|
||||
}
|
||||
|
||||
// MarshalInterface takes any value and marshals it into a yaml document
|
||||
// MarshalValue takes any value and marshals it into a yaml document
|
||||
func (store Store) MarshalValue(v interface{}) ([]byte, error) {
|
||||
v = store.treeValueToYamlValue(v)
|
||||
return (&yaml.YAMLMarshaler{Indent: 4}).Marshal(v)
|
||||
}
|
||||
|
||||
// UnmarshalMetadata takes a yaml document as a string and extracts sops' metadata from it
|
||||
func (s *Store) UnmarshalMetadata(in []byte) (sops.Metadata, error) {
|
||||
func (store *Store) UnmarshalMetadata(in []byte) (sops.Metadata, error) {
|
||||
file := stores.SopsFile{}
|
||||
err := yaml.Unmarshal(in, &file)
|
||||
if err != nil {
|
||||
|
|
Загрузка…
Ссылка в новой задаче