Signed-off-by: Edoardo Tenani <edoardo.tenani@pm.me>
This commit is contained in:
Edoardo Tenani 2024-06-23 16:04:50 +02:00
Родитель 3458c3534f
Коммит b8e65f9dd1
3 изменённых файлов: 113 добавлений и 0 удалений

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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")
}
})
}
}

Просмотреть файл

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