github.com/greenpau/go-authcrunch@v1.1.4/config_test.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 authcrunch 16 17 import ( 18 "fmt" 19 "github.com/greenpau/go-authcrunch/internal/tests" 20 "github.com/greenpau/go-authcrunch/internal/testutils" 21 "github.com/greenpau/go-authcrunch/pkg/acl" 22 "github.com/greenpau/go-authcrunch/pkg/authn" 23 "github.com/greenpau/go-authcrunch/pkg/authz" 24 "github.com/greenpau/go-authcrunch/pkg/credentials" 25 "github.com/greenpau/go-authcrunch/pkg/errors" 26 "github.com/greenpau/go-authcrunch/pkg/idp" 27 "github.com/greenpau/go-authcrunch/pkg/ids" 28 "github.com/greenpau/go-authcrunch/pkg/messaging" 29 "path" 30 "path/filepath" 31 "testing" 32 ) 33 34 func TestNewConfig(t *testing.T) { 35 db, err := testutils.CreateTestDatabase("TestNewPortal") 36 if err != nil { 37 t.Fatalf("failed to create temp dir: %v", err) 38 } 39 dbPath := db.GetPath() 40 // t.Logf("%v", dbPath) 41 42 var testcases = []struct { 43 name string 44 45 identityStores []*ids.IdentityStoreConfig 46 identityProviders []*idp.IdentityProviderConfig 47 credentials []credentials.Credential 48 messaging []messaging.Provider 49 portals []*authn.PortalConfig 50 policies []*authz.PolicyConfig 51 52 shouldErr bool 53 errPhase string 54 err error 55 }{ 56 { 57 name: "test empty config", 58 shouldErr: true, 59 errPhase: "Validate", 60 err: fmt.Errorf("no portals and gatekeepers found"), 61 }, 62 { 63 name: "test failed local identity store config", 64 identityStores: []*ids.IdentityStoreConfig{ 65 { 66 Name: "localdb", 67 Kind: "local", 68 Params: map[string]interface{}{ 69 "realm": "local", 70 }, 71 }, 72 }, 73 shouldErr: true, 74 errPhase: "AddIdentityStore", 75 err: errors.ErrIdentityStoreConfigInvalid.WithArgs( 76 fmt.Errorf("required field %q not found", "path"), 77 ), 78 }, 79 { 80 name: "test local identity stores having same realm but different paths", 81 identityStores: []*ids.IdentityStoreConfig{ 82 { 83 Name: "localdb1", 84 Kind: "local", 85 Params: map[string]interface{}{ 86 "realm": "local", 87 "path": filepath.Join(path.Dir(dbPath), "user_db1.json"), 88 }, 89 }, 90 { 91 Name: "localdb2", 92 Kind: "local", 93 Params: map[string]interface{}{ 94 "realm": "local", 95 "path": filepath.Join(path.Dir(dbPath), "user_db2.json"), 96 }, 97 }, 98 }, 99 portals: []*authn.PortalConfig{ 100 { 101 Name: "myportal", 102 IdentityStores: []string{ 103 "localdb1", 104 "localdb2", 105 }, 106 }, 107 }, 108 shouldErr: true, 109 errPhase: "Validate", 110 err: fmt.Errorf("identity provider %q has the same %q realm as %q", "localdb2", "local", "localdb1"), 111 }, 112 { 113 name: "test local identity stores having different realms but the same path", 114 identityStores: []*ids.IdentityStoreConfig{ 115 { 116 Name: "localdb1", 117 Kind: "local", 118 Params: map[string]interface{}{ 119 "realm": "contoso", 120 "path": filepath.Join(path.Dir(dbPath), "user_db.json"), 121 }, 122 }, 123 }, 124 identityProviders: []*idp.IdentityProviderConfig{ 125 { 126 Name: "provider1", 127 Kind: "oauth", 128 Params: map[string]interface{}{ 129 "base_auth_url": "https://localhost/oauth", 130 "token_url": "https://localhost/oauth/access_token", 131 "authorization_url": "https://localhost/oauth/authorize", 132 "client_id": "foo", 133 "client_secret": "bar", 134 "driver": "generic", 135 "realm": "contoso", 136 "required_token_fields": []interface{}{"access_token"}, 137 "response_type": []interface{}{"code"}, 138 139 "tls_insecure_skip_verify": true, 140 "key_verification_disabled": true, 141 "jwks_keys": map[string]string{ 142 "87329db33bf": "testdata/oauth/87329db33bf_pub.pem", 143 }, 144 }, 145 }, 146 }, 147 portals: []*authn.PortalConfig{ 148 { 149 Name: "myportal", 150 IdentityStores: []string{ 151 "localdb1", 152 }, 153 IdentityProviders: []string{ 154 "provider1", 155 }, 156 }, 157 }, 158 shouldErr: true, 159 errPhase: "Validate", 160 err: fmt.Errorf("identity provider %q has the same %q realm as %q", "provider1", "contoso", "localdb1"), 161 }, 162 { 163 name: "test failed identity provider config", 164 identityProviders: []*idp.IdentityProviderConfig{ 165 { 166 Name: "authp", 167 Kind: "oauth", 168 Params: map[string]interface{}{ 169 "realm": "authp", 170 }, 171 }, 172 }, 173 shouldErr: true, 174 errPhase: "AddIdentityProvider", 175 err: errors.ErrIdentityProviderConfigInvalid.WithArgs( 176 fmt.Errorf("required field %q not found", "driver"), 177 ), 178 }, 179 { 180 name: "test failed auth portal config", 181 portals: []*authn.PortalConfig{ 182 { 183 Name: "myportal", 184 }, 185 }, 186 shouldErr: true, 187 errPhase: "Validate", 188 err: errors.ErrPortalConfigBackendsNotFound, 189 }, 190 { 191 name: "test failed credentials config", 192 credentials: []credentials.Credential{ 193 &credentials.Generic{ 194 Name: "foobar", 195 Username: "foo", 196 }, 197 }, 198 shouldErr: true, 199 errPhase: "AddCredential", 200 err: errors.ErrCredKeyValueEmpty.WithArgs("password"), 201 }, 202 { 203 name: "test failed messaging provider config", 204 messaging: []messaging.Provider{ 205 &messaging.EmailProvider{ 206 Name: "default", 207 Address: "localhost", 208 // Protocol: "smtp", 209 Credentials: "foobar", 210 SenderEmail: "root@localhost", 211 }, 212 }, 213 shouldErr: true, 214 errPhase: "AddMessagingProvider", 215 err: errors.ErrMessagingProviderKeyValueEmpty.WithArgs("protocol"), 216 }, 217 { 218 name: "test failed authorization policy config", 219 policies: []*authz.PolicyConfig{ 220 { 221 Name: "mygatekeeper", 222 }, 223 }, 224 shouldErr: true, 225 errPhase: "AddAuthorizationPolicy", 226 err: errors.ErrInvalidConfiguration.WithArgs("mygatekeeper", "access list rule config not found"), 227 }, 228 { 229 name: "test valid local auth config", 230 credentials: []credentials.Credential{ 231 &credentials.Generic{ 232 Name: "foobar", 233 Username: "foo", 234 Password: "bar", 235 }, 236 }, 237 messaging: []messaging.Provider{ 238 &messaging.EmailProvider{ 239 Name: "default", 240 Address: "localhost", 241 Protocol: "smtp", 242 Credentials: "foobar", 243 SenderEmail: "root@localhost", 244 }, 245 }, 246 identityStores: []*ids.IdentityStoreConfig{ 247 { 248 Name: "localdb", 249 Kind: "local", 250 Params: map[string]interface{}{ 251 "realm": "local", 252 "path": dbPath, 253 }, 254 }, 255 }, 256 identityProviders: []*idp.IdentityProviderConfig{ 257 { 258 Name: "contoso", 259 Kind: "oauth", 260 Params: map[string]interface{}{ 261 "base_auth_url": "https://localhost/oauth", 262 "token_url": "https://localhost/oauth/access_token", 263 "authorization_url": "https://localhost/oauth/authorize", 264 "client_id": "foo", 265 "client_secret": "bar", 266 "driver": "generic", 267 "realm": "contoso", 268 "required_token_fields": []interface{}{"access_token"}, 269 "response_type": []interface{}{"code"}, 270 271 "tls_insecure_skip_verify": true, 272 "key_verification_disabled": true, 273 "jwks_keys": map[string]string{ 274 "87329db33bf": "testdata/oauth/87329db33bf_pub.pem", 275 }, 276 }, 277 }, 278 }, 279 portals: []*authn.PortalConfig{ 280 { 281 Name: "myportal", 282 IdentityStores: []string{ 283 "localdb", 284 }, 285 }, 286 }, 287 policies: []*authz.PolicyConfig{ 288 { 289 Name: "mygatekeeper", 290 AccessListRules: []*acl.RuleConfiguration{ 291 { 292 Conditions: []string{ 293 "match roles authp/admin authp/user", 294 }, 295 Action: "allow stop", 296 }, 297 }, 298 AuthRedirectDisabled: true, 299 }, 300 }, 301 }, 302 } 303 304 for _, tc := range testcases { 305 t.Run(tc.name, func(t *testing.T) { 306 msgs := []string{fmt.Sprintf("test name: %s", tc.name)} 307 308 cfg := NewConfig() 309 310 for _, item := range tc.credentials { 311 err := cfg.AddCredential(item) 312 if tests.EvalErrPhaseWithLog(t, err, "AddCredential", tc.errPhase, tc.shouldErr, tc.err, msgs) { 313 return 314 } 315 } 316 317 for _, item := range tc.messaging { 318 err := cfg.AddMessagingProvider(item) 319 if tests.EvalErrPhaseWithLog(t, err, "AddMessagingProvider", tc.errPhase, tc.shouldErr, tc.err, msgs) { 320 return 321 } 322 } 323 324 for _, item := range tc.identityStores { 325 err := cfg.AddIdentityStore(item.Name, item.Kind, item.Params) 326 if tests.EvalErrPhaseWithLog(t, err, "AddIdentityStore", tc.errPhase, tc.shouldErr, tc.err, msgs) { 327 return 328 } 329 } 330 331 for _, item := range tc.identityProviders { 332 err := cfg.AddIdentityProvider(item.Name, item.Kind, item.Params) 333 if tests.EvalErrPhaseWithLog(t, err, "AddIdentityProvider", tc.errPhase, tc.shouldErr, tc.err, msgs) { 334 return 335 } 336 } 337 338 for _, item := range tc.portals { 339 err := cfg.AddAuthenticationPortal(item) 340 if tests.EvalErrPhaseWithLog(t, err, "AddAuthenticationPortal", tc.errPhase, tc.shouldErr, tc.err, msgs) { 341 return 342 } 343 } 344 345 for _, item := range tc.policies { 346 err := cfg.AddAuthorizationPolicy(item) 347 if tests.EvalErrPhaseWithLog(t, err, "AddAuthorizationPolicy", tc.errPhase, tc.shouldErr, tc.err, msgs) { 348 return 349 } 350 } 351 352 err := cfg.Validate() 353 if err != nil { 354 if tests.EvalErrPhaseWithLog(t, err, "Validate", tc.errPhase, tc.shouldErr, tc.err, msgs) { 355 return 356 } 357 } 358 if tc.shouldErr { 359 t.Fatalf("unexpected success, want: %v", tc.err) 360 } 361 }) 362 } 363 }