summaryrefslogtreecommitdiff
path: root/internal/configuration/provider.go
diff options
context:
space:
mode:
authorJames Elliott <james-d-elliott@users.noreply.github.com>2025-02-18 20:38:36 +1100
committerGitHub <noreply@github.com>2025-02-18 09:38:36 +0000
commita9d1986fa9dec8701ee73b05aa99781f4bbe5f18 (patch)
treebbcef1a55483271f43308179d4fd09ef8a894131 /internal/configuration/provider.go
parent7ac3c6a4f3945c3c4272bac717addd1ef598b2b9 (diff)
feat(configuration): reusable definitions (#8077)
This adds reusable definitions into the mix for the configuration. This replaces the existing networks section for the access_control section and is automatically remapped for users. Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
Diffstat (limited to 'internal/configuration/provider.go')
-rw-r--r--internal/configuration/provider.go96
1 files changed, 88 insertions, 8 deletions
diff --git a/internal/configuration/provider.go b/internal/configuration/provider.go
index c4f68260d..77c0b3577 100644
--- a/internal/configuration/provider.go
+++ b/internal/configuration/provider.go
@@ -2,6 +2,7 @@ package configuration
import (
"fmt"
+ "net"
"github.com/go-viper/mapstructure/v2"
"github.com/knadh/koanf/v2"
@@ -13,21 +14,18 @@ import (
func Load(val *schema.StructValidator, sources ...Source) (keys []string, configuration *schema.Configuration, err error) {
configuration = &schema.Configuration{}
- keys, err = LoadAdvanced(val, "", configuration, sources...)
+ keys, err = LoadAdvanced(val, "", configuration, nil, sources...)
return keys, configuration, err
}
// LoadAdvanced is intended to give more flexibility over loading a particular path to a specific interface.
-func LoadAdvanced(val *schema.StructValidator, path string, result any, sources ...Source) (keys []string, err error) {
+func LoadAdvanced(val *schema.StructValidator, path string, result any, definitions *schema.Definitions, sources ...Source) (keys []string, err error) {
if val == nil {
return keys, errNoValidator
}
- ko := koanf.NewWithConf(koanf.Conf{
- Delim: constDelimiter,
- StrictMerge: false,
- })
+ ko := koanf.NewWithConf(koanf.Conf{Delim: constDelimiter, StrictMerge: false})
if err = loadSources(ko, val, sources...); err != nil {
return ko.Keys(), err
@@ -39,11 +37,88 @@ func LoadAdvanced(val *schema.StructValidator, path string, result any, sources
return koanfGetKeys(ko), err
}
- unmarshal(final, val, path, result)
+ unmarshal(final, val, path, result, definitions)
+
+ mapDefinitionsResult(val, result)
return koanfGetKeys(final), nil
}
+func LoadDefinitions(val *schema.StructValidator, sources ...Source) (definitions *schema.Definitions, err error) {
+ ko := koanf.NewWithConf(koanf.Conf{Delim: constDelimiter, StrictMerge: false})
+
+ if err = loadSources(ko, val, sources...); err != nil {
+ return nil, err
+ }
+
+ var final *koanf.Koanf
+
+ if final, err = koanfRemapKeys(val, ko, deprecations, deprecationsMKM); err != nil {
+ return nil, err
+ }
+
+ legacy := &legacyDefinitions{}
+
+ c := koanf.UnmarshalConf{
+ DecoderConfig: &mapstructure.DecoderConfig{
+ DecodeHook: mapstructure.ComposeDecodeHookFunc(
+ mapstructure.StringToSliceHookFunc(","),
+ StringToIPNetworksHookFunc(nil),
+ ),
+ Metadata: nil,
+ Result: legacy,
+ WeaklyTypedInput: true,
+ },
+ }
+
+ if err = final.UnmarshalWithConf("", legacy, c); err != nil {
+ val.Push(fmt.Errorf("error occurred during unmarshalling definitions configuration: %w", err))
+ }
+
+ d := legacy.Definitions
+
+ mapDefinitions(val, legacy.AccessControl.Networks, &d)
+
+ return &d, nil
+}
+
+func mapDefinitionsResult(val *schema.StructValidator, result any) {
+ if config, ok := result.(*schema.Configuration); ok {
+ mapDefinitions(val, config.AccessControl.Networks, &config.Definitions)
+ }
+}
+
+func mapDefinitions(val *schema.StructValidator, networks []schema.AccessControlNetwork, definitions *schema.Definitions) {
+ if len(networks) == 0 {
+ return
+ }
+
+ var ok bool
+
+ if definitions.Network == nil {
+ definitions.Network = make(map[string][]*net.IPNet, len(networks))
+ }
+
+ for _, network := range networks {
+ if _, ok = definitions.Network[network.Name]; ok {
+ val.Push(fmt.Errorf("error occurred during unmarshalling definitions configuration: the definition for network with name '%s' exists in both the definitions section and access control section which is not permitted", network.Name))
+
+ continue
+ }
+
+ definitions.Network[network.Name] = network.Networks
+ }
+}
+
+type legacyDefinitions struct {
+ Definitions schema.Definitions `koanf:"definitions"`
+ AccessControl legacyAccessControl `koanf:"access_control"`
+}
+
+type legacyAccessControl struct {
+ Networks []schema.AccessControlNetwork `koanf:"networks"`
+}
+
func mapHasKey(k string, m map[string]any) bool {
if _, ok := m[k]; ok {
return true
@@ -52,7 +127,11 @@ func mapHasKey(k string, m map[string]any) bool {
return false
}
-func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o any) {
+func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o any, definitions *schema.Definitions) {
+ if definitions == nil {
+ definitions = &schema.Definitions{}
+ }
+
c := koanf.UnmarshalConf{
DecoderConfig: &mapstructure.DecoderConfig{
DecodeHook: mapstructure.ComposeDecodeHookFunc(
@@ -68,6 +147,7 @@ func unmarshal(ko *koanf.Koanf, val *schema.StructValidator, path string, o any)
StringToCryptographicKeyHookFunc(),
StringToTLSVersionHookFunc(),
StringToPasswordDigestHookFunc(),
+ StringToIPNetworksHookFunc(definitions.Network),
ToTimeDurationHookFunc(),
ToRefreshIntervalDurationHookFunc(),
),