github.com/greenpau/go-authcrunch@v1.1.4/pkg/ids/config.go (about) 1 // Copyright 2022 Paul Greenberg greenpau@outlook.com 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ids 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "github.com/greenpau/go-authcrunch/pkg/errors" 21 "github.com/greenpau/go-authcrunch/pkg/ids/ldap" 22 "github.com/greenpau/go-authcrunch/pkg/ids/local" 23 ) 24 25 // IdentityStoreConfig represents an identity store configuration. 26 type IdentityStoreConfig struct { 27 Name string `json:"name,omitempty" xml:"name,omitempty" yaml:"name,omitempty"` 28 Kind string `json:"kind,omitempty" xml:"kind,omitempty" yaml:"kind,omitempty"` 29 Params map[string]interface{} `json:"params,omitempty" xml:"params,omitempty" yaml:"params,omitempty"` 30 } 31 32 // NewIdentityStoreConfig returns IdentityStoreConfig instance. 33 func NewIdentityStoreConfig(name, kind string, params map[string]interface{}) (*IdentityStoreConfig, error) { 34 cfg := &IdentityStoreConfig{ 35 Name: name, 36 Kind: kind, 37 Params: params, 38 } 39 if err := cfg.Validate(); err != nil { 40 return nil, err 41 } 42 return cfg, nil 43 } 44 45 // Validate validates identity store config. 46 func (cfg *IdentityStoreConfig) Validate() error { 47 var requiredFields, optionalFields []string 48 if cfg.Name == "" { 49 return errors.ErrIdentityStoreConfigInvalid.WithArgs("empty identity store name") 50 } 51 52 switch cfg.Kind { 53 case "local": 54 requiredFields = []string{ 55 "realm", 56 "path", 57 } 58 optionalFields = []string{ 59 "users", 60 "login_icon", 61 "registration_enabled", 62 "username_recovery_enabled", 63 "password_recovery_enabled", 64 "contact_support_enabled", 65 "support_link", 66 "support_email", 67 } 68 case "ldap": 69 requiredFields = []string{ 70 "realm", 71 "servers", 72 "groups", 73 } 74 optionalFields = []string{ 75 "bind_username", 76 "bind_password", 77 "attributes", 78 "trusted_authorities", 79 "search_base_dn", 80 "search_user_filter", 81 "search_group_filter", 82 "login_icon", 83 "registration_enabled", 84 "username_recovery_enabled", 85 "password_recovery_enabled", 86 "contact_support_enabled", 87 "support_link", 88 "support_email", 89 "fallback_roles", 90 } 91 case "": 92 return errors.ErrIdentityStoreConfigInvalid.WithArgs("empty identity store type") 93 default: 94 return errors.ErrIdentityStoreConfigInvalid.WithArgs("unsupported identity store type " + cfg.Kind) 95 } 96 97 if err := validateFields(cfg.Params, requiredFields, optionalFields); err != nil { 98 return errors.ErrIdentityStoreConfigInvalid.WithArgs(err) 99 } 100 101 b, _ := json.Marshal(cfg.Params) 102 switch cfg.Kind { 103 case "local": 104 config := &local.Config{} 105 json.Unmarshal(b, config) 106 config.Name = cfg.Name 107 if err := config.Validate(); err != nil { 108 return errors.ErrIdentityProviderConfigInvalid.WithArgs(err) 109 } 110 case "ldap": 111 config := &ldap.Config{} 112 json.Unmarshal(b, config) 113 config.Name = cfg.Name 114 if err := config.Validate(); err != nil { 115 return errors.ErrIdentityProviderConfigInvalid.WithArgs(err) 116 } 117 } 118 119 return nil 120 } 121 122 func validateFields(m map[string]interface{}, requiredFields, optionalFields []string) error { 123 if m == nil || len(m) == 0 { 124 return fmt.Errorf("empty identity store parameters") 125 } 126 127 for _, k := range requiredFields { 128 if _, exists := m[k]; !exists { 129 return fmt.Errorf("required field %q not found", k) 130 } 131 } 132 133 allFields := append(optionalFields, requiredFields...) 134 for k := range m { 135 var found bool 136 for _, f := range allFields { 137 if f == k { 138 found = true 139 } 140 } 141 if !found { 142 return fmt.Errorf("found unsupported %q field", k) 143 } 144 } 145 146 return nil 147 }