Skip to content

Commit

Permalink
Support using comments to select parts to encrypt
Browse files Browse the repository at this point in the history
Signed-off-by: Mitar <[email protected]>
  • Loading branch information
mitar committed Sep 22, 2023
1 parent b7da2fc commit 3cd2bfe
Show file tree
Hide file tree
Showing 9 changed files with 580 additions and 182 deletions.
11 changes: 10 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1438,9 +1438,18 @@ that match the supplied regular expression. For example, this command:
will not encrypt the values under the ``description`` and ``metadata`` keys in a YAML file
containing kubernetes secrets, while encrypting everything else.
For YAML files, another method is to use ``--encrypted-comment-regex`` which will
only encrypt comments and values which have a preceding comment matching the supplied
regular expression.
Conversely, you can opt in to only left certain keys without encrypting by using the
``--unencrypted-comment-regex`` option, which will leave the values and comments
unencrypted when they have a preeceding comment that matches the supplied regular expression.
You can also specify these options in the ``.sops.yaml`` config file.
Note: these four options ``--unencrypted-suffix``, ``--encrypted-suffix``, ``--encrypted-regex`` and ``--unencrypted-regex`` are
Note: these six options ``--unencrypted-suffix``, ``--encrypted-suffix``, ``--encrypted-regex``,
``--unencrypted-regex``, ``--encrypted-comment-regex``, and ``--unencrypted-comment-regex`` are
mutually exclusive and cannot all be used in the same file.
Encryption Protocol
Expand Down
30 changes: 17 additions & 13 deletions cmd/sops/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,14 @@ type editOpts struct {

type editExampleOpts struct {
editOpts
UnencryptedSuffix string
EncryptedSuffix string
UnencryptedRegex string
EncryptedRegex string
KeyGroups []sops.KeyGroup
GroupThreshold int
UnencryptedSuffix string
EncryptedSuffix string
UnencryptedRegex string
EncryptedRegex string
UnencryptedCommentRegex string
EncryptedCommentRegex string
KeyGroups []sops.KeyGroup
GroupThreshold int
}

type runEditorUntilOkOpts struct {
Expand All @@ -60,13 +62,15 @@ func editExample(opts editExampleOpts) ([]byte, error) {
tree := sops.Tree{
Branches: branches,
Metadata: sops.Metadata{
KeyGroups: opts.KeyGroups,
UnencryptedSuffix: opts.UnencryptedSuffix,
EncryptedSuffix: opts.EncryptedSuffix,
UnencryptedRegex: opts.UnencryptedRegex,
EncryptedRegex: opts.EncryptedRegex,
Version: version.Version,
ShamirThreshold: opts.GroupThreshold,
KeyGroups: opts.KeyGroups,
UnencryptedSuffix: opts.UnencryptedSuffix,
EncryptedSuffix: opts.EncryptedSuffix,
UnencryptedRegex: opts.UnencryptedRegex,
EncryptedRegex: opts.EncryptedRegex,
UnencryptedCommentRegex: opts.UnencryptedCommentRegex,
EncryptedCommentRegex: opts.EncryptedCommentRegex,
Version: version.Version,
ShamirThreshold: opts.GroupThreshold,
},
FilePath: path,
}
Expand Down
40 changes: 22 additions & 18 deletions cmd/sops/encrypt.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@ import (
)

type encryptOpts struct {
Cipher sops.Cipher
InputStore sops.Store
OutputStore sops.Store
InputPath string
KeyServices []keyservice.KeyServiceClient
UnencryptedSuffix string
EncryptedSuffix string
UnencryptedRegex string
EncryptedRegex string
KeyGroups []sops.KeyGroup
GroupThreshold int
Cipher sops.Cipher
InputStore sops.Store
OutputStore sops.Store
InputPath string
KeyServices []keyservice.KeyServiceClient
UnencryptedSuffix string
EncryptedSuffix string
UnencryptedRegex string
EncryptedRegex string
UnencryptedCommentRegex string
EncryptedCommentRegex string
KeyGroups []sops.KeyGroup
GroupThreshold int
}

type fileAlreadyEncryptedError struct{}
Expand Down Expand Up @@ -77,13 +79,15 @@ func encrypt(opts encryptOpts) (encryptedFile []byte, err error) {
tree := sops.Tree{
Branches: branches,
Metadata: sops.Metadata{
KeyGroups: opts.KeyGroups,
UnencryptedSuffix: opts.UnencryptedSuffix,
EncryptedSuffix: opts.EncryptedSuffix,
UnencryptedRegex: opts.UnencryptedRegex,
EncryptedRegex: opts.EncryptedRegex,
Version: version.Version,
ShamirThreshold: opts.GroupThreshold,
KeyGroups: opts.KeyGroups,
UnencryptedSuffix: opts.UnencryptedSuffix,
EncryptedSuffix: opts.EncryptedSuffix,
UnencryptedRegex: opts.UnencryptedRegex,
EncryptedRegex: opts.EncryptedRegex,
UnencryptedCommentRegex: opts.UnencryptedCommentRegex,
EncryptedCommentRegex: opts.EncryptedCommentRegex,
Version: version.Version,
ShamirThreshold: opts.GroupThreshold,
},
FilePath: path,
}
Expand Down
70 changes: 48 additions & 22 deletions cmd/sops/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -678,11 +678,19 @@ func main() {
},
cli.StringFlag{
Name: "unencrypted-regex",
Usage: "set the unencrypted key suffix. When specified, only keys matching the regex will be left unencrypted.",
Usage: "set the unencrypted key regex. When specified, only keys matching the regex will be left unencrypted.",
},
cli.StringFlag{
Name: "encrypted-regex",
Usage: "set the encrypted key suffix. When specified, only keys matching the regex will be encrypted.",
Usage: "set the encrypted key regex. When specified, only keys matching the regex will be encrypted.",
},
cli.StringFlag{
Name: "unencrypted-comment-regex",
Usage: "set the unencrypted comment suffix. When specified, only keys that have comment matching the regex will be left unencrypted.",
},
cli.StringFlag{
Name: "encrypted-comment-regex",
Usage: "set the encrypted comment suffix. When specified, only keys that have comment matching the regex will be encrypted.",
},
cli.StringFlag{
Name: "config",
Expand Down Expand Up @@ -738,6 +746,8 @@ func main() {
encryptedSuffix := c.String("encrypted-suffix")
encryptedRegex := c.String("encrypted-regex")
unencryptedRegex := c.String("unencrypted-regex")
encryptedCommentRegex := c.String("encrypted-comment-regex")
unencryptedCommentRegex := c.String("unencrypted-comment-regex")
conf, err := loadConfig(c, fileName, nil)
if err != nil {
return toExitError(err)
Expand All @@ -756,6 +766,12 @@ func main() {
if unencryptedRegex == "" {
unencryptedRegex = conf.UnencryptedRegex
}
if encryptedCommentRegex == "" {
encryptedCommentRegex = conf.EncryptedCommentRegex
}
if unencryptedCommentRegex == "" {
unencryptedCommentRegex = conf.UnencryptedCommentRegex
}
}

cryptRuleCount := 0
Expand All @@ -771,12 +787,18 @@ func main() {
if unencryptedRegex != "" {
cryptRuleCount++
}
if encryptedCommentRegex != "" {
cryptRuleCount++
}
if unencryptedCommentRegex != "" {
cryptRuleCount++
}

if cryptRuleCount > 1 {
return common.NewExitError("Error: cannot use more than one of encrypted_suffix, unencrypted_suffix, encrypted_regex or unencrypted_regex in the same file", codes.ErrorConflictingParameters)
return common.NewExitError("Error: cannot use more than one of encrypted_suffix, unencrypted_suffix, encrypted_regex, unencrypted_regex, encrypted_comment_regex, or unencrypted_comment_regex in the same file", codes.ErrorConflictingParameters)
}

// only supply the default UnencryptedSuffix when EncryptedSuffix and EncryptedRegex are not provided
// only supply the default UnencryptedSuffix when EncryptedSuffix, EncryptedRegex, and others are not provided
if cryptRuleCount == 0 {
unencryptedSuffix = sops.DefaultUnencryptedSuffix
}
Expand All @@ -798,17 +820,19 @@ func main() {
return toExitError(err)
}
output, err = encrypt(encryptOpts{
OutputStore: outputStore,
InputStore: inputStore,
InputPath: fileName,
Cipher: aes.NewCipher(),
UnencryptedSuffix: unencryptedSuffix,
EncryptedSuffix: encryptedSuffix,
UnencryptedRegex: unencryptedRegex,
EncryptedRegex: encryptedRegex,
KeyServices: svcs,
KeyGroups: groups,
GroupThreshold: threshold,
OutputStore: outputStore,
InputStore: inputStore,
InputPath: fileName,
Cipher: aes.NewCipher(),
UnencryptedSuffix: unencryptedSuffix,
EncryptedSuffix: encryptedSuffix,
UnencryptedRegex: unencryptedRegex,
EncryptedRegex: encryptedRegex,
UnencryptedCommentRegex: unencryptedCommentRegex,
EncryptedCommentRegex: encryptedCommentRegex,
KeyServices: svcs,
KeyGroups: groups,
GroupThreshold: threshold,
})
}

Expand Down Expand Up @@ -953,13 +977,15 @@ func main() {
return toExitError(err)
}
output, err = editExample(editExampleOpts{
editOpts: opts,
UnencryptedSuffix: unencryptedSuffix,
EncryptedSuffix: encryptedSuffix,
UnencryptedRegex: unencryptedRegex,
EncryptedRegex: encryptedRegex,
KeyGroups: groups,
GroupThreshold: threshold,
editOpts: opts,
UnencryptedSuffix: unencryptedSuffix,
EncryptedSuffix: encryptedSuffix,
UnencryptedRegex: unencryptedRegex,
EncryptedRegex: encryptedRegex,
UnencryptedCommentRegex: unencryptedCommentRegex,
EncryptedCommentRegex: encryptedCommentRegex,
KeyGroups: groups,
GroupThreshold: threshold,
})
}
}
Expand Down
73 changes: 44 additions & 29 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,20 +109,22 @@ type destinationRule struct {
}

type creationRule struct {
PathRegex string `yaml:"path_regex"`
KMS string
AwsProfile string `yaml:"aws_profile"`
Age string `yaml:"age"`
PGP string
GCPKMS string `yaml:"gcp_kms"`
AzureKeyVault string `yaml:"azure_keyvault"`
VaultURI string `yaml:"hc_vault_transit_uri"`
KeyGroups []keyGroup `yaml:"key_groups"`
ShamirThreshold int `yaml:"shamir_threshold"`
UnencryptedSuffix string `yaml:"unencrypted_suffix"`
EncryptedSuffix string `yaml:"encrypted_suffix"`
UnencryptedRegex string `yaml:"unencrypted_regex"`
EncryptedRegex string `yaml:"encrypted_regex"`
PathRegex string `yaml:"path_regex"`
KMS string
AwsProfile string `yaml:"aws_profile"`
Age string `yaml:"age"`
PGP string
GCPKMS string `yaml:"gcp_kms"`
AzureKeyVault string `yaml:"azure_keyvault"`
VaultURI string `yaml:"hc_vault_transit_uri"`
KeyGroups []keyGroup `yaml:"key_groups"`
ShamirThreshold int `yaml:"shamir_threshold"`
UnencryptedSuffix string `yaml:"unencrypted_suffix"`
EncryptedSuffix string `yaml:"encrypted_suffix"`
UnencryptedRegex string `yaml:"unencrypted_regex"`
EncryptedRegex string `yaml:"encrypted_regex"`
UnencryptedCommentRegex string `yaml:"unencrypted_comment_regex"`
EncryptedCommentRegex string `yaml:"encrypted_comment_regex"`
}

// Load loads a sops config file into a temporary struct
Expand All @@ -136,14 +138,16 @@ func (f *configFile) load(bytes []byte) error {

// Config is the configuration for a given SOPS file
type Config struct {
KeyGroups []sops.KeyGroup
ShamirThreshold int
UnencryptedSuffix string
EncryptedSuffix string
UnencryptedRegex string
EncryptedRegex string
Destination publish.Destination
OmitExtensions bool
KeyGroups []sops.KeyGroup
ShamirThreshold int
UnencryptedSuffix string
EncryptedSuffix string
UnencryptedRegex string
EncryptedRegex string
UnencryptedCommentRegex string
EncryptedCommentRegex string
Destination publish.Destination
OmitExtensions bool
}

func getKeyGroupsFromCreationRule(cRule *creationRule, kmsEncryptionContext map[string]*string) ([]sops.KeyGroup, error) {
Expand Down Expand Up @@ -242,12 +246,21 @@ func configFromRule(rule *creationRule, kmsEncryptionContext map[string]*string)
if rule.EncryptedSuffix != "" {
cryptRuleCount++
}
if rule.UnencryptedRegex != "" {
cryptRuleCount++
}
if rule.EncryptedRegex != "" {
cryptRuleCount++
}
if rule.UnencryptedCommentRegex != "" {
cryptRuleCount++
}
if rule.EncryptedCommentRegex != "" {
cryptRuleCount++
}

if cryptRuleCount > 1 {
return nil, fmt.Errorf("error loading config: cannot use more than one of encrypted_suffix, unencrypted_suffix, or encrypted_regex for the same rule")
return nil, fmt.Errorf("error loading config: cannot use more than one of encrypted_suffix, unencrypted_suffix, encrypted_regex, unencrypted_regex, encrypted_comment_regex, or unencrypted_comment_regex for the same rule")
}

groups, err := getKeyGroupsFromCreationRule(rule, kmsEncryptionContext)
Expand All @@ -256,12 +269,14 @@ func configFromRule(rule *creationRule, kmsEncryptionContext map[string]*string)
}

return &Config{
KeyGroups: groups,
ShamirThreshold: rule.ShamirThreshold,
UnencryptedSuffix: rule.UnencryptedSuffix,
EncryptedSuffix: rule.EncryptedSuffix,
UnencryptedRegex: rule.UnencryptedRegex,
EncryptedRegex: rule.EncryptedRegex,
KeyGroups: groups,
ShamirThreshold: rule.ShamirThreshold,
UnencryptedSuffix: rule.UnencryptedSuffix,
EncryptedSuffix: rule.EncryptedSuffix,
UnencryptedRegex: rule.UnencryptedRegex,
EncryptedRegex: rule.EncryptedRegex,
UnencryptedCommentRegex: rule.UnencryptedCommentRegex,
EncryptedCommentRegex: rule.EncryptedCommentRegex,
}, nil
}

Expand Down
Loading

0 comments on commit 3cd2bfe

Please sign in to comment.