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

Merge pull request #545 from endorama/add-filestatus-command

add filestatus command
This commit is contained in:
Felix Fontein
2024-06-24 07:30:54 +02:00
committed by GitHub
4 changed files with 146 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ import (
"github.com/getsops/sops/v3/cmd/sops/codes"
"github.com/getsops/sops/v3/cmd/sops/common"
"github.com/getsops/sops/v3/cmd/sops/subcommand/exec"
filestatuscmd "github.com/getsops/sops/v3/cmd/sops/subcommand/filestatus"
"github.com/getsops/sops/v3/cmd/sops/subcommand/groups"
keyservicecmd "github.com/getsops/sops/v3/cmd/sops/subcommand/keyservice"
publishcmd "github.com/getsops/sops/v3/cmd/sops/subcommand/publish"
@@ -428,6 +429,38 @@ func main() {
return nil
},
},
{
Name: "filestatus",
Usage: "check the status of the file, returning encryption status",
ArgsUsage: `file`,
Flags: []cli.Flag{},
Action: func(c *cli.Context) error {
if c.NArg() < 1 {
return common.NewExitError("Error: no file specified", codes.NoFileSpecified)
}
fileName := c.Args()[0]
inputStore := inputStore(c, fileName)
opts := filestatuscmd.Opts{
InputStore: inputStore,
InputPath: fileName,
}
status, err := filestatuscmd.FileStatus(opts)
if err != nil {
return err
}
json, err := encodingjson.Marshal(status)
if err != nil {
return common.NewExitError(err, codes.ErrorGeneric)
}
fmt.Println(string(json))
return nil
},
},
{
Name: "groups",
Usage: "modify the groups on a SOPS file",

View File

@@ -0,0 +1,60 @@
package filestatus
import (
"fmt"
"github.com/getsops/sops/v3"
"github.com/getsops/sops/v3/cmd/sops/common"
)
// Opts represent the input options for FileStatus
type Opts struct {
InputStore sops.Store
InputPath string
}
// Status represents the status of a file
type Status struct {
// Encrypted represents whether the file provided is encrypted by SOPS
Encrypted bool `json:"encrypted"`
}
// FileStatus checks encryption status of a file
func FileStatus(opts Opts) (Status, error) {
encrypted, err := cfs(opts.InputStore, opts.InputPath)
if err != nil {
return Status{}, fmt.Errorf("cannot check file status: %w", err)
}
return Status{Encrypted: encrypted}, nil
}
// cfs checks and reports on file encryption status.
//
// It tries to decrypt the input file with the provided store.
// It returns true if the file contains sops metadata, false
// if it doesn't or Version or MessageAuthenticationCode are
// not found.
// It reports any error encountered different from
// sops.MetadataNotFound, as that is used to detect a sops
// encrypted file.
func cfs(s sops.Store, inputpath string) (bool, error) {
tree, err := common.LoadEncryptedFile(s, inputpath)
if err != nil && err == sops.MetadataNotFound {
return false, nil
}
if err != nil {
return false, fmt.Errorf("cannot load encrypted file: %w", err)
}
// NOTE: even if it's a file that sops recognize as containing
// valid metadata, we want to ensure some metadata are present
// to report the file as encrypted.
if tree.Metadata.Version == "" {
return false, nil
}
if tree.Metadata.MessageAuthenticationCode == "" {
return false, nil
}
return true, nil
}

View File

@@ -0,0 +1,52 @@
package filestatus
import (
"path"
"testing"
"github.com/getsops/sops/v3/cmd/sops/common"
"github.com/getsops/sops/v3/config"
"github.com/stretchr/testify/require"
)
const repoRoot = "../../../../"
func fromRepoRoot(p string) string {
return path.Join(repoRoot, p)
}
func TestFileStatus(t *testing.T) {
tests := []struct {
name string
file string
expectedEncrypted bool
}{
{
name: "encrypted file should be reported as such",
file: "example.yaml",
expectedEncrypted: true,
},
{
name: "plain text file should be reported as cleartext",
file: "functional-tests/res/plainfile.yaml",
},
{
name: "file without mac should be reported as cleartext",
file: "functional-tests/res/plainfile.yaml",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := fromRepoRoot(tt.file)
s := common.DefaultStoreForPath(config.NewStoresConfig(), f)
encrypted, err := cfs(s, f)
require.Nil(t, err, "should not error")
if tt.expectedEncrypted {
require.True(t, encrypted, "file should have been reported as encrypted")
} else {
require.False(t, encrypted, "file should have been reported as cleartext")
}
})
}
}

View File

@@ -0,0 +1 @@
hello: world