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

Ignore encryption selection options for binary store (and warn when they are used).

Signed-off-by: Felix Fontein <felix@fontein.de>
This commit is contained in:
Felix Fontein
2025-08-30 11:04:09 +02:00
parent 8117a49639
commit ffc1e265bb
6 changed files with 82 additions and 6 deletions

View File

@@ -1023,7 +1023,7 @@ func main() {
}
svcs := keyservices(c)
encConfig, err := getEncryptConfig(c, fileNameOverride, nil)
encConfig, err := getEncryptConfig(c, fileNameOverride, inputStore, nil)
if err != nil {
return toExitError(err)
}
@@ -1369,7 +1369,7 @@ func main() {
}
} else {
// File doesn't exist, edit the example file instead
encConfig, err := getEncryptConfig(c, fileName, nil)
encConfig, err := getEncryptConfig(c, fileName, inputStore, nil)
if err != nil {
return toExitError(err)
}
@@ -1908,7 +1908,7 @@ func main() {
}
var output []byte
if isEncryptMode {
encConfig, err := getEncryptConfig(c, fileNameOverride, config)
encConfig, err := getEncryptConfig(c, fileNameOverride, inputStore, config)
if err != nil {
return toExitError(err)
}
@@ -1996,7 +1996,7 @@ func main() {
output, err = edit(opts)
} else {
// File doesn't exist, edit the example file instead
encConfig, err := getEncryptConfig(c, fileNameOverride, config)
encConfig, err := getEncryptConfig(c, fileNameOverride, inputStore, config)
if err != nil {
return toExitError(err)
}
@@ -2050,7 +2050,7 @@ func main() {
}
}
func getEncryptConfig(c *cli.Context, fileName string, optionalConfig *config.Config) (encryptConfig, error) {
func getEncryptConfig(c *cli.Context, fileName string, inputStore common.Store, optionalConfig *config.Config) (encryptConfig, error) {
unencryptedSuffix := c.String("unencrypted-suffix")
encryptedSuffix := c.String("encrypted-suffix")
encryptedRegex := c.String("encrypted-regex")
@@ -2090,6 +2090,33 @@ func getEncryptConfig(c *cli.Context, fileName string, optionalConfig *config.Co
}
}
if inputStore.IsSingleValueStore() {
// Warn about settings that potentially disable encryption of the single key.
if unencryptedSuffix != "" {
log.Warn(fmt.Sprintf("Using an unencrypted suffix does not make sense with the input store (the %s store produces one key that should always be encrypted) and will be ignored.", inputStore.Name()))
}
if encryptedSuffix != "" {
log.Warn(fmt.Sprintf("Using an encrypted suffix does not make sense with the input store (the %s store produces one key that should always be encrypted) and will be ignored.", inputStore.Name()))
}
if encryptedRegex != "" {
log.Warn(fmt.Sprintf("Using an encrypted regex does not make sense with the input store (the %s store produces one key that should always be encrypted) and will be ignored.", inputStore.Name()))
}
if unencryptedRegex != "" {
log.Warn(fmt.Sprintf("Using an unencrypted regex does not make sense with the input store (the %s store produces one key that should always be encrypted) and will be ignored.", inputStore.Name()))
}
if encryptedCommentRegex != "" {
log.Warn(fmt.Sprintf("Using an encrypted comment regex does not make sense with the input store (the %s store never produces comments) and will be ignored.", inputStore.Name()))
}
// Do not warn about unencryptedCommentRegex and macOnlyEncrypted since they cannot have any effect.
unencryptedSuffix = ""
encryptedSuffix = ""
encryptedRegex = ""
unencryptedRegex = ""
encryptedCommentRegex = ""
unencryptedCommentRegex = ""
macOnlyEncrypted = false
}
cryptRuleCount := 0
if unencryptedSuffix != "" {
cryptRuleCount++
@@ -2115,7 +2142,7 @@ func getEncryptConfig(c *cli.Context, fileName string, optionalConfig *config.Co
}
// only supply the default UnencryptedSuffix when EncryptedSuffix, EncryptedRegex, and others are not provided
if cryptRuleCount == 0 {
if cryptRuleCount == 0 && !inputStore.IsSingleValueStore() {
unencryptedSuffix = sops.DefaultUnencryptedSuffix
}

View File

@@ -726,6 +726,12 @@ type CheckEncrypted interface {
HasSopsTopLevelKey(TreeBranch) bool
}
// SingleValueStore is the interface for determining whether a store uses only
// one single key and no comments. This is basically identifying the binary store.
type SingleValueStore interface {
IsSingleValueStore() bool
}
// Store is used to interact with files, both encrypted and unencrypted.
type Store interface {
EncryptedFileLoader
@@ -734,6 +740,8 @@ type Store interface {
PlainFileEmitter
ValueEmitter
CheckEncrypted
SingleValueStore
Name() string
}
// MasterKeyCount returns the number of master keys available

View File

@@ -23,6 +23,14 @@ func NewStore(c *config.DotenvStoreConfig) *Store {
return &Store{config: *c}
}
func (store *Store) IsSingleValueStore() bool {
return false
}
func (store *Store) Name() string {
return "dotenv"
}
// LoadEncryptedFile loads an encrypted file's bytes onto a sops.Tree runtime object
func (store *Store) LoadEncryptedFile(in []byte) (sops.Tree, error) {
branches, err := store.LoadPlainFile(in)

View File

@@ -21,6 +21,14 @@ func NewStore(c *config.INIStoreConfig) *Store {
return &Store{config: c}
}
func (store *Store) IsSingleValueStore() bool {
return false
}
func (store *Store) Name() string {
return "ini"
}
func (store Store) encodeTree(branches sops.TreeBranches) ([]byte, error) {
iniFile := ini.Empty(ini.LoadOptions{AllowNonUniqueSections: true})
iniFile.DeleteSection(ini.DefaultSection)

View File

@@ -22,12 +22,29 @@ func NewStore(c *config.JSONStoreConfig) *Store {
return &Store{config: *c}
}
func (store *Store) IsSingleValueStore() bool {
return false
}
func (store *Store) Name() string {
return "json"
}
// BinaryStore handles storage of binary data in a JSON envelope.
type BinaryStore struct {
store Store
config config.JSONBinaryStoreConfig
}
// The binary store uses a single key ("data") to store everything.
func (store *BinaryStore) IsSingleValueStore() bool {
return true
}
func (store *BinaryStore) Name() string {
return "binary"
}
func NewBinaryStore(c *config.JSONBinaryStoreConfig) *BinaryStore {
return &BinaryStore{config: *c, store: *NewStore(&config.JSONStoreConfig{
Indent: c.Indent,

View File

@@ -24,6 +24,14 @@ func NewStore(c *config.YAMLStoreConfig) *Store {
return &Store{config: *c}
}
func (store *Store) IsSingleValueStore() bool {
return false
}
func (store *Store) Name() string {
return "yaml"
}
func (store Store) appendCommentToList(comment string, list []interface{}) []interface{} {
if comment != "" {
for _, commentLine := range strings.Split(comment, "\n") {