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

Resolves #1864. Adds Native List as an option for configuring keys in addition to the trailing comma option already given.

Signed-off-by: Lucas Earl <earl.lucas@gmail.com>
This commit is contained in:
Lucas Earl
2025-06-24 00:10:21 -06:00
committed by Felix Fontein
parent fd277e0786
commit 6312f36bdf
2 changed files with 115 additions and 23 deletions

View File

@@ -170,23 +170,78 @@ 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"`
UnencryptedCommentRegex string `yaml:"unencrypted_comment_regex"`
EncryptedCommentRegex string `yaml:"encrypted_comment_regex"`
MACOnlyEncrypted bool `yaml:"mac_only_encrypted"`
PathRegex string `yaml:"path_regex"`
KMS interface{} `yaml:"kms"` // string or []string
AwsProfile string `yaml:"aws_profile"`
Age interface{} `yaml:"age"` // string or []string
PGP interface{} `yaml:"pgp"` // string or []string
GCPKMS interface{} `yaml:"gcp_kms"` // string or []string
AzureKeyVault interface{} `yaml:"azure_keyvault"` // string or []string
VaultURI interface{} `yaml:"hc_vault_transit_uri"` // string or []string
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"`
MACOnlyEncrypted bool `yaml:"mac_only_encrypted"`
}
// Helper methods to safely extract keys as []string
func (c *creationRule) GetKMSKeys() []string {
return parseKeyField(c.KMS)
}
func (c *creationRule) GetAgeKeys() []string {
return parseKeyField(c.Age)
}
func (c *creationRule) GetPGPKeys() []string {
return parseKeyField(c.PGP)
}
func (c *creationRule) GetGCPKMSKeys() []string {
return parseKeyField(c.GCPKMS)
}
func (c *creationRule) GetAzureKeyVaultKeys() []string {
return parseKeyField(c.AzureKeyVault)
}
func (c *creationRule) GetVaultURIs() []string {
return parseKeyField(c.VaultURI)
}
// Utility function to handle both string and []string
func parseKeyField(field interface{}) []string {
switch v := field.(type) {
case string:
if v == "" {
return []string{}
}
// Existing CSV parsing logic
keys := strings.Split(v, ",")
result := make([]string, 0, len(keys))
for _, key := range keys {
trimmed := strings.TrimSpace(key)
if trimmed != "" { // Skip empty strings (fixes trailing comma issue)
result = append(result, trimmed)
}
}
return result
case []interface{}:
result := make([]string, len(v))
for i, item := range v {
result[i] = fmt.Sprintf("%v", item)
}
return result
case []string:
return v
default:
return []string{}
}
}
func NewStoresConfig() *StoresConfig {
@@ -292,7 +347,7 @@ func getKeyGroupsFromCreationRule(cRule *creationRule, kmsEncryptionContext map[
} else {
var keyGroup sops.KeyGroup
if cRule.Age != "" {
ageKeys, err := age.MasterKeysFromRecipients(cRule.Age)
ageKeys, err := age.MasterKeysFromRecipients(strings.Join(cRule.GetAgeKeys(), ","))
if err != nil {
return nil, err
} else {
@@ -301,23 +356,23 @@ func getKeyGroupsFromCreationRule(cRule *creationRule, kmsEncryptionContext map[
}
}
}
for _, k := range pgp.MasterKeysFromFingerprintString(cRule.PGP) {
for _, k := range pgp.MasterKeysFromFingerprintString(strings.Join(cRule.GetPGPKeys(), ",")) {
keyGroup = append(keyGroup, k)
}
for _, k := range kms.MasterKeysFromArnString(cRule.KMS, kmsEncryptionContext, cRule.AwsProfile) {
for _, k := range kms.MasterKeysFromArnString(strings.Join(cRule.GetKMSKeys(), ","), kmsEncryptionContext, cRule.AwsProfile) {
keyGroup = append(keyGroup, k)
}
for _, k := range gcpkms.MasterKeysFromResourceIDString(cRule.GCPKMS) {
for _, k := range gcpkms.MasterKeysFromResourceIDString(strings.Join(cRule.GetGCPKMSKeys(), ",")) {
keyGroup = append(keyGroup, k)
}
azureKeys, err := azkv.MasterKeysFromURLs(cRule.AzureKeyVault)
azureKeys, err := azkv.MasterKeysFromURLs(strings.Join(cRule.GetAzureKeyVaultKeys(), ","))
if err != nil {
return nil, err
}
for _, k := range azureKeys {
keyGroup = append(keyGroup, k)
}
vaultKeys, err := hcvault.NewMasterKeysFromURIs(cRule.VaultURI)
vaultKeys, err := hcvault.NewMasterKeysFromURIs(strings.Join(cRule.GetVaultURIs(), ","))
if err != nil {
return nil, err
}

View File

@@ -718,3 +718,40 @@ func TestLoadConfigFileWithVaultDestinationRules(t *testing.T) {
assert.NotNil(t, conf.Destination)
assert.Contains(t, conf.Destination.Path("barfoo"), "/v1/kv/barfoo/barfoo")
}
func TestCreationRuleNativeKeyLists(t *testing.T) {
var sampleConfigWithNativeKeyLists = []byte(`
creation_rules:
- path_regex: native_list*
pgp:
- "85D77543B3D624B63CEA9E6DBC17301B491B3F21" # name@email.com
- "FBC7B9E2A4F9289AC0C1D4843D16CEE4A27381B4" # server_XYZ
kms:
- "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
age:
- "age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p"
gcp_kms:
- "projects/test-project/locations/global/keyRings/test-ring/cryptoKeys/test-key"
hc_vault_transit_uri:
- "https://vault.example.com:8200/v1/transit/keys/key1"
`)
conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithNativeKeyLists, t), "/conf/path", "native_list_test", nil)
assert.Nil(t, err)
if conf == nil {
t.Fatal("Expected configuration but got nil")
}
assert.True(t, len(conf.KeyGroups) > 0)
assert.True(t, len(conf.KeyGroups[0]) == 6)
keyTypeCounts := make(map[string]int)
for _, key := range conf.KeyGroups[0] {
keyTypeCounts[key.TypeToIdentifier()]++
}
assert.Equal(t, 2, keyTypeCounts["pgp"])
assert.Equal(t, 1, keyTypeCounts["kms"])
assert.Equal(t, 1, keyTypeCounts["age"])
assert.Equal(t, 1, keyTypeCounts["gcp_kms"])
assert.Equal(t, 1, keyTypeCounts["hc_vault"])
}