From 9fbc9ea89c57979b37d77cbd6d7b5e1bff02f361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Badst=C3=BCbner?= Date: Tue, 23 Apr 2024 17:20:39 +0200 Subject: [PATCH] feat(config): merge key_groups closes #1123 --- config/config.go | 73 ++++++++++++++++++++++++++----------------- config/config_test.go | 40 ++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 28 deletions(-) diff --git a/config/config.go b/config/config.go index 643268682..3908a9319 100644 --- a/config/config.go +++ b/config/config.go @@ -94,6 +94,7 @@ type configFile struct { } type keyGroup struct { + Merge []keyGroup KMS []kmsKey GCPKMS []gcpKmsKey `yaml:"gcp_kms"` AzureKV []azureKVKey `yaml:"azure_keyvault"` @@ -180,38 +181,54 @@ type Config struct { OmitExtensions bool } +func extractMasterKeys(group keyGroup) (sops.KeyGroup, error) { + var keyGroup sops.KeyGroup + for _, k := range group.Merge { + subKeyGroup, err := extractMasterKeys(k) + if err != nil { + return nil, err + } + keyGroup = append(keyGroup, subKeyGroup...) + } + + for _, k := range group.Age { + keys, err := age.MasterKeysFromRecipients(k) + if err != nil { + return nil, err + } + for _, key := range keys { + keyGroup = append(keyGroup, key) + } + } + for _, k := range group.PGP { + keyGroup = append(keyGroup, pgp.NewMasterKeyFromFingerprint(k)) + } + for _, k := range group.KMS { + keyGroup = append(keyGroup, kms.NewMasterKeyWithProfile(k.Arn, k.Role, k.Context, k.AwsProfile)) + } + for _, k := range group.GCPKMS { + keyGroup = append(keyGroup, gcpkms.NewMasterKeyFromResourceID(k.ResourceID)) + } + for _, k := range group.AzureKV { + keyGroup = append(keyGroup, azkv.NewMasterKey(k.VaultURL, k.Key, k.Version)) + } + for _, k := range group.Vault { + if masterKey, err := hcvault.NewMasterKeyFromURI(k); err == nil { + keyGroup = append(keyGroup, masterKey) + } else { + return nil, err + } + } + return keyGroup, nil +} + func getKeyGroupsFromCreationRule(cRule *creationRule, kmsEncryptionContext map[string]*string) ([]sops.KeyGroup, error) { var groups []sops.KeyGroup if len(cRule.KeyGroups) > 0 { for _, group := range cRule.KeyGroups { - var keyGroup sops.KeyGroup - for _, k := range group.Age { - keys, err := age.MasterKeysFromRecipients(k) - if err != nil { - return nil, err - } - for _, key := range keys { - keyGroup = append(keyGroup, key) - } - } - for _, k := range group.PGP { - keyGroup = append(keyGroup, pgp.NewMasterKeyFromFingerprint(k)) - } - for _, k := range group.KMS { - keyGroup = append(keyGroup, kms.NewMasterKeyWithProfile(k.Arn, k.Role, k.Context, k.AwsProfile)) - } - for _, k := range group.GCPKMS { - keyGroup = append(keyGroup, gcpkms.NewMasterKeyFromResourceID(k.ResourceID)) - } - for _, k := range group.AzureKV { - keyGroup = append(keyGroup, azkv.NewMasterKey(k.VaultURL, k.Key, k.Version)) - } - for _, k := range group.Vault { - if masterKey, err := hcvault.NewMasterKeyFromURI(k); err == nil { - keyGroup = append(keyGroup, masterKey) - } else { - return nil, err - } + keyGroup, err := extractMasterKeys(group) + if err != nil { + return nil, err } groups = append(groups, keyGroup) } diff --git a/config/config_test.go b/config/config_test.go index 8f4fb006b..ef4d927f1 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -120,6 +120,40 @@ creation_rules: - 'https://baz.vault:8200/v1/baz/keys/baz-key' `) +var sampleConfigWithMergeType = []byte(` +creation_rules: + - path_regex: "" + key_groups: + - merge: + - kms: + - arn: foo + aws_profile: bar + pgp: + - bar + gcp_kms: + - resource_id: foo + azure_keyvault: + - vaultUrl: https://foo.vault.azure.net + key: foo-key + version: fooversion + hc_vault: + - 'https://foo.vault:8200/v1/foo/keys/foo-key' + - kms: + - arn: baz + aws_profile: foo + pgp: + - qux + gcp_kms: + - resource_id: bar + - resource_id: baz + azure_keyvault: + - vaultUrl: https://bar.vault.azure.net + key: bar-key + version: barversion + hc_vault: + - 'https://baz.vault:8200/v1/baz/keys/baz-key' +`) + var sampleConfigWithSuffixParameters = []byte(` creation_rules: - path_regex: foobar* @@ -324,6 +358,12 @@ func TestLoadConfigFileWithGroups(t *testing.T) { assert.Equal(t, expected, conf) } +func TestLoadConfigFileWithMerge(t *testing.T) { + conf, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithMergeType, t), "/conf/path", "whatever", nil) + assert.Nil(t, err) + assert.Equal(t, 11, len(conf.KeyGroups[0])) +} + func TestLoadConfigFileWithNoMatchingRules(t *testing.T) { _, err := parseCreationRuleForFile(parseConfigFile(sampleConfigWithNoMatchingRules, t), "/conf/path", "foobar2000", nil) assert.NotNil(t, err)