Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions cmd/sops/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/getsops/sops/v3/stores/yaml"
"github.com/getsops/sops/v3/version"
"github.com/mitchellh/go-wordwrap"
"github.com/urfave/cli"
"github.com/urfave/cli/v3"
"golang.org/x/term"
)

Expand Down Expand Up @@ -85,23 +85,23 @@ type DecryptTreeOpts struct {
func DecryptTree(opts DecryptTreeOpts) (dataKey []byte, err error) {
dataKey, err = opts.Tree.Metadata.GetDataKeyWithKeyServices(opts.KeyServices, opts.DecryptionOrder)
if err != nil {
return nil, NewExitError(err, codes.CouldNotRetrieveKey)
return nil, Exit(err, codes.CouldNotRetrieveKey)
}
computedMac, err := opts.Tree.Decrypt(dataKey, opts.Cipher)
if err != nil {
return nil, NewExitError(fmt.Sprintf("Error decrypting tree: %s", err), codes.ErrorDecryptingTree)
return nil, Exit(fmt.Sprintf("Error decrypting tree: %s", err), codes.ErrorDecryptingTree)
}
fileMac, err := opts.Cipher.Decrypt(opts.Tree.Metadata.MessageAuthenticationCode, dataKey, opts.Tree.Metadata.LastModified.Format(time.RFC3339))
if !opts.IgnoreMac {
if err != nil {
return nil, NewExitError(fmt.Sprintf("Cannot decrypt MAC: %s", err), codes.MacMismatch)
return nil, Exit(fmt.Sprintf("Cannot decrypt MAC: %s", err), codes.MacMismatch)
}
if fileMac != computedMac {
// If the file has an empty MAC, display "no MAC" instead of not displaying anything
if fileMac == "" {
fileMac = "no MAC"
}
return nil, NewExitError(fmt.Sprintf("MAC mismatch. File has %s, computed %s", fileMac, computedMac), codes.MacMismatch)
return nil, Exit(fmt.Sprintf("MAC mismatch. File has %s, computed %s", fileMac, computedMac), codes.MacMismatch)
}
}
return dataKey, nil
Expand All @@ -121,12 +121,12 @@ type EncryptTreeOpts struct {
func EncryptTree(opts EncryptTreeOpts) error {
unencryptedMac, err := opts.Tree.Encrypt(opts.DataKey, opts.Cipher)
if err != nil {
return NewExitError(fmt.Sprintf("Error encrypting tree: %s", err), codes.ErrorEncryptingTree)
return Exit(fmt.Sprintf("Error encrypting tree: %s", err), codes.ErrorEncryptingTree)
}
opts.Tree.Metadata.LastModified = time.Now().UTC()
opts.Tree.Metadata.MessageAuthenticationCode, err = opts.Cipher.Encrypt(unencryptedMac, opts.DataKey, opts.Tree.Metadata.LastModified.Format(time.RFC3339))
if err != nil {
return NewExitError(fmt.Sprintf("Could not encrypt MAC: %s", err), codes.ErrorEncryptingMac)
return Exit(fmt.Sprintf("Could not encrypt MAC: %s", err), codes.ErrorEncryptingMac)
}
return nil
}
Expand All @@ -138,12 +138,12 @@ func LoadEncryptedFileEx(loader sops.EncryptedFileLoader, inputPath string, read
if readFromStdin {
fileBytes, err = io.ReadAll(os.Stdin)
if err != nil {
return nil, NewExitError(fmt.Sprintf("Error reading from stdin: %s", err), codes.CouldNotReadInputFile)
return nil, Exit(fmt.Sprintf("Error reading from stdin: %s", err), codes.CouldNotReadInputFile)
}
} else {
fileBytes, err = os.ReadFile(inputPath)
if err != nil {
return nil, NewExitError(fmt.Sprintf("Error reading file: %s", err), codes.CouldNotReadInputFile)
return nil, Exit(fmt.Sprintf("Error reading file: %s", err), codes.CouldNotReadInputFile)
}
}
path, err := filepath.Abs(inputPath)
Expand All @@ -160,13 +160,13 @@ func LoadEncryptedFile(loader sops.EncryptedFileLoader, inputPath string) (*sops
return LoadEncryptedFileEx(loader, inputPath, false)
}

// NewExitError returns a cli.ExitError given an error (wrapped in a generic interface{})
// Exit returns a cli.ExitCoder given an error (wrapped in a generic interface{})
// and an exit code to represent the failure
func NewExitError(i interface{}, exitCode int) *cli.ExitError {
func Exit(i interface{}, exitCode int) cli.ExitCoder {
if userErr, ok := i.(sops.UserError); ok {
return NewExitError(userErr.UserError(), exitCode)
return Exit(userErr.UserError(), exitCode)
}
return cli.NewExitError(i, exitCode)
return cli.Exit(i, exitCode)
}

// StoreForFormat returns the correct format-specific implementation
Expand Down Expand Up @@ -312,7 +312,7 @@ func FixAWSKMSEncryptionContextBug(opts GenericDecryptOpts, tree *sops.Tree) (*s
}

if dataKey == nil {
return nil, NewExitError(fmt.Sprintf("Failed to decrypt, meaning there is likely another problem from the encryption context bug: %s", err), codes.ErrorDecryptingTree)
return nil, Exit(fmt.Sprintf("Failed to decrypt, meaning there is likely another problem from the encryption context bug: %s", err), codes.ErrorDecryptingTree)
}

errs := tree.Metadata.UpdateMasterKeysWithKeyServices(dataKey, opts.KeyServices)
Expand All @@ -337,12 +337,12 @@ func FixAWSKMSEncryptionContextBug(opts GenericDecryptOpts, tree *sops.Tree) (*s

encryptedFile, err := opts.InputStore.EmitEncryptedFile(*tree)
if err != nil {
return nil, NewExitError(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)
return nil, Exit(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)
}

file, err := os.Create(opts.InputPath)
if err != nil {
return nil, NewExitError(fmt.Sprintf("Could not open file for writing: %s", err), codes.CouldNotWriteOutputFile)
return nil, Exit(fmt.Sprintf("Could not open file for writing: %s", err), codes.CouldNotWriteOutputFile)
}
defer file.Close()
_, err = file.Write(encryptedFile)
Expand Down
59 changes: 0 additions & 59 deletions cmd/sops/completion.go

This file was deleted.

6 changes: 3 additions & 3 deletions cmd/sops/decrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func decrypt(opts decryptOpts) (decryptedFile []byte, err error) {
err = fmt.Errorf("%s\n\n%s", err.Error(), notBinaryHint)
}
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Error dumping file: %s", err), codes.ErrorDumpingTree)
return nil, common.Exit(fmt.Sprintf("Error dumping file: %s", err), codes.ErrorDumpingTree)
}
return decryptedFile, err
}
Expand All @@ -84,15 +84,15 @@ func extract(tree *sops.Tree, path []interface{}, outputStore sops.Store) (outpu
err = fmt.Errorf("%s\n\n%s", err.Error(), notBinaryHint)
}
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Error dumping file: %s", err), codes.ErrorDumpingTree)
return nil, common.Exit(fmt.Sprintf("Error dumping file: %s", err), codes.ErrorDumpingTree)
}
return decrypted, err
} else if str, ok := v.(string); ok {
return []byte(str), nil
}
bytes, err := outputStore.EmitValue(v)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Error dumping tree: %s", err), codes.ErrorDumpingTree)
return nil, common.Exit(fmt.Sprintf("Error dumping tree: %s", err), codes.ErrorDumpingTree)
}
return bytes, nil
}
28 changes: 14 additions & 14 deletions cmd/sops/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func editExample(opts editExampleOpts) ([]byte, error) {
fileBytes := opts.InputStore.EmitExample()
branches, err := opts.InputStore.LoadPlainFile(fileBytes)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Error unmarshalling file: %s", err), codes.CouldNotReadInputFile)
return nil, common.Exit(fmt.Sprintf("Error unmarshalling file: %s", err), codes.CouldNotReadInputFile)
}
path, err := filepath.Abs(opts.InputPath)
if err != nil {
Expand All @@ -62,7 +62,7 @@ func editExample(opts editExampleOpts) ([]byte, error) {
// Generate a data key
dataKey, errs := tree.GenerateDataKeyWithKeyServices(opts.KeyServices)
if len(errs) > 0 {
return nil, common.NewExitError(fmt.Sprintf("Error encrypting the data key with one or more master keys: %s", errs), codes.CouldNotRetrieveKey)
return nil, common.Exit(fmt.Sprintf("Error encrypting the data key with one or more master keys: %s", errs), codes.CouldNotRetrieveKey)
}

return editTree(opts.editOpts, &tree, dataKey)
Expand Down Expand Up @@ -99,19 +99,19 @@ func editTree(opts editOpts, tree *sops.Tree, dataKey []byte) ([]byte, error) {
// Create temporary file for editing
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Could not create temporary directory: %s", err), codes.CouldNotWriteOutputFile)
return nil, common.Exit(fmt.Sprintf("Could not create temporary directory: %s", err), codes.CouldNotWriteOutputFile)
}
defer os.RemoveAll(tmpdir)

tmpfile, err := os.Create(filepath.Join(tmpdir, filepath.Base(opts.InputPath)))
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Could not create temporary file: %s", err), codes.CouldNotWriteOutputFile)
return nil, common.Exit(fmt.Sprintf("Could not create temporary file: %s", err), codes.CouldNotWriteOutputFile)
}
// Ensure that in any case, the temporary file is always closed.
defer tmpfile.Close()
// Ensure that the file is read+write for owner only.
if err = tmpfile.Chmod(0600); err != nil {
return nil, common.NewExitError(fmt.Sprintf("Could not change permissions of temporary file to read-write for owner only: %s", err), codes.CouldNotWriteOutputFile)
return nil, common.Exit(fmt.Sprintf("Could not change permissions of temporary file to read-write for owner only: %s", err), codes.CouldNotWriteOutputFile)
}

tmpfileName := tmpfile.Name()
Expand All @@ -124,17 +124,17 @@ func editTree(opts editOpts, tree *sops.Tree, dataKey []byte) ([]byte, error) {
out, err = opts.OutputStore.EmitPlainFile(tree.Branches)
}
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)
return nil, common.Exit(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)
}
_, err = tmpfile.Write(out)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Could not write output file: %s", err), codes.CouldNotWriteOutputFile)
return nil, common.Exit(fmt.Sprintf("Could not write output file: %s", err), codes.CouldNotWriteOutputFile)
}

// Compute file hash to detect if the file has been edited
origHash, err := hashFile(tmpfileName)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Could not hash file: %s", err), codes.CouldNotReadInputFile)
return nil, common.Exit(fmt.Sprintf("Could not hash file: %s", err), codes.CouldNotReadInputFile)
}

// Close the temporary file, so that an editor can open it.
Expand Down Expand Up @@ -164,7 +164,7 @@ func editTree(opts editOpts, tree *sops.Tree, dataKey []byte) ([]byte, error) {
// Output the file
encryptedFile, err := opts.OutputStore.EmitEncryptedFile(*tree)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)
return nil, common.Exit(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)
}
return encryptedFile, nil
}
Expand All @@ -173,18 +173,18 @@ func runEditorUntilOk(opts runEditorUntilOkOpts) error {
for {
err := runEditor(opts.TmpFileName)
if err != nil {
return common.NewExitError(fmt.Sprintf("Could not run editor: %s", err), codes.NoEditorFound)
return common.Exit(fmt.Sprintf("Could not run editor: %s", err), codes.NoEditorFound)
}
newHash, err := hashFile(opts.TmpFileName)
if err != nil {
return common.NewExitError(fmt.Sprintf("Could not hash file: %s", err), codes.CouldNotReadInputFile)
return common.Exit(fmt.Sprintf("Could not hash file: %s", err), codes.CouldNotReadInputFile)
}
if bytes.Equal(newHash, opts.OriginalHash) {
return common.NewExitError("File has not changed, exiting.", codes.FileHasNotBeenModified)
return common.Exit("File has not changed, exiting.", codes.FileHasNotBeenModified)
}
edited, err := os.ReadFile(opts.TmpFileName)
if err != nil {
return common.NewExitError(fmt.Sprintf("Could not read edited file: %s", err), codes.CouldNotReadInputFile)
return common.Exit(fmt.Sprintf("Could not read edited file: %s", err), codes.CouldNotReadInputFile)
}
newBranches, err := opts.InputStore.LoadPlainFile(edited)
if err != nil {
Expand Down Expand Up @@ -217,7 +217,7 @@ func runEditorUntilOk(opts runEditorUntilOkOpts) error {
opts.Tree.Branches = newBranches
needVersionUpdated, err := version.AIsNewerThanB(version.Version, opts.Tree.Metadata.Version)
if err != nil {
return common.NewExitError(fmt.Sprintf("Failed to compare document version %q with program version %q: %v", opts.Tree.Metadata.Version, version.Version, err), codes.FailedToCompareVersions)
return common.Exit(fmt.Sprintf("Failed to compare document version %q with program version %q: %v", opts.Tree.Metadata.Version, version.Version, err), codes.FailedToCompareVersions)
}
if needVersionUpdated {
opts.Tree.Metadata.Version = version.Version
Expand Down
12 changes: 6 additions & 6 deletions cmd/sops/encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,23 @@ func encrypt(opts encryptOpts) (encryptedFile []byte, err error) {
if opts.ReadFromStdin {
fileBytes, err = io.ReadAll(os.Stdin)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Error reading from stdin: %s", err), codes.CouldNotReadInputFile)
return nil, common.Exit(fmt.Sprintf("Error reading from stdin: %s", err), codes.CouldNotReadInputFile)
}
} else {
fileBytes, err = os.ReadFile(opts.InputPath)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Error reading file: %s", err), codes.CouldNotReadInputFile)
return nil, common.Exit(fmt.Sprintf("Error reading file: %s", err), codes.CouldNotReadInputFile)
}
}
branches, err := opts.InputStore.LoadPlainFile(fileBytes)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Error unmarshalling file: %s", err), codes.CouldNotReadInputFile)
return nil, common.Exit(fmt.Sprintf("Error unmarshalling file: %s", err), codes.CouldNotReadInputFile)
}
if len(branches) < 1 {
return nil, common.NewExitError("File cannot be completely empty, it must contain at least one document", codes.NeedAtLeastOneDocument)
return nil, common.Exit("File cannot be completely empty, it must contain at least one document", codes.NeedAtLeastOneDocument)
}
if err := ensureNoMetadata(opts, branches[0]); err != nil {
return nil, common.NewExitError(err, codes.FileAlreadyEncrypted)
return nil, common.Exit(err, codes.FileAlreadyEncrypted)
}
path, err := filepath.Abs(opts.InputPath)
if err != nil {
Expand Down Expand Up @@ -128,7 +128,7 @@ func encrypt(opts encryptOpts) (encryptedFile []byte, err error) {

encryptedFile, err = opts.OutputStore.EmitEncryptedFile(tree)
if err != nil {
return nil, common.NewExitError(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)
return nil, common.Exit(fmt.Sprintf("Could not marshal tree: %s", err), codes.ErrorDumpingTree)
}
return
}
Loading