github.com/greenpau/go-authcrunch@v1.1.4/server_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  
    20  	"github.com/google/go-cmp/cmp"
    21  	"github.com/greenpau/go-authcrunch/internal/tests"
    22  	"github.com/greenpau/go-authcrunch/internal/testutils"
    23  	"github.com/greenpau/go-authcrunch/pkg/acl"
    24  	"github.com/greenpau/go-authcrunch/pkg/authn"
    25  
    26  	// "github.com/greenpau/go-authcrunch/pkg/authn/registration"
    27  	"github.com/greenpau/go-authcrunch/pkg/authz"
    28  	"github.com/greenpau/go-authcrunch/pkg/credentials"
    29  
    30  	// "github.com/greenpau/go-authcrunch/pkg/errors"
    31  	"testing"
    32  
    33  	"github.com/greenpau/go-authcrunch/pkg/idp"
    34  	"github.com/greenpau/go-authcrunch/pkg/ids"
    35  	"github.com/greenpau/go-authcrunch/pkg/messaging"
    36  	logutil "github.com/greenpau/go-authcrunch/pkg/util/log"
    37  	"go.uber.org/zap"
    38  )
    39  
    40  func TestNewServer(t *testing.T) {
    41  	db, err := testutils.CreateTestDatabase("TestNewPortal")
    42  	if err != nil {
    43  		t.Fatalf("failed to create temp dir: %v", err)
    44  	}
    45  	dbPath := db.GetPath()
    46  	// t.Logf("%v", dbPath)
    47  
    48  	var testcases = []struct {
    49  		name   string
    50  		logger *zap.Logger
    51  
    52  		identityStores    []*ids.IdentityStoreConfig
    53  		identityProviders []*idp.IdentityProviderConfig
    54  		credentials       []credentials.Credential
    55  		messaging         []messaging.Provider
    56  		portals           []*authn.PortalConfig
    57  		policies          []*authz.PolicyConfig
    58  
    59  		want string
    60  
    61  		shouldErr bool
    62  		err       error
    63  	}{
    64  		{
    65  			name:      "test server without portals and gatekeepers",
    66  			logger:    logutil.NewLogger(),
    67  			shouldErr: true,
    68  			err:       fmt.Errorf("no portals and gatekeepers found"),
    69  		},
    70  		{
    71  			name:   "test server with valid local auth config",
    72  			logger: logutil.NewLogger(),
    73  			credentials: []credentials.Credential{
    74  				&credentials.Generic{
    75  					Name:     "foobar",
    76  					Username: "foo",
    77  					Password: "bar",
    78  				},
    79  			},
    80  			messaging: []messaging.Provider{
    81  				&messaging.EmailProvider{
    82  					Name:        "default",
    83  					Address:     "localhost",
    84  					Protocol:    "smtp",
    85  					Credentials: "foobar",
    86  					SenderEmail: "root@localhost",
    87  				},
    88  			},
    89  			identityStores: []*ids.IdentityStoreConfig{
    90  				{
    91  					Name: "localdb",
    92  					Kind: "local",
    93  					Params: map[string]interface{}{
    94  						"realm": "local",
    95  						"path":  dbPath,
    96  					},
    97  				},
    98  			},
    99  			identityProviders: []*idp.IdentityProviderConfig{
   100  				{
   101  					Name: "contoso",
   102  					Kind: "oauth",
   103  					Params: map[string]interface{}{
   104  						"base_auth_url":         "https://localhost/oauth",
   105  						"token_url":             "https://localhost/oauth/access_token",
   106  						"authorization_url":     "https://localhost/oauth/authorize",
   107  						"client_id":             "foo",
   108  						"client_secret":         "bar",
   109  						"driver":                "generic",
   110  						"realm":                 "contoso",
   111  						"required_token_fields": []interface{}{"access_token"},
   112  						"response_type":         []interface{}{"code"},
   113  
   114  						"tls_insecure_skip_verify":  true,
   115  						"key_verification_disabled": true,
   116  						"jwks_keys": map[string]string{
   117  							"87329db33bf": "testdata/oauth/87329db33bf_pub.pem",
   118  						},
   119  					},
   120  				},
   121  			},
   122  			portals: []*authn.PortalConfig{
   123  				{
   124  					Name: "myportal",
   125  					IdentityStores: []string{
   126  						"localdb",
   127  					},
   128  				},
   129  			},
   130  			policies: []*authz.PolicyConfig{
   131  				{
   132  					Name: "mygatekeeper",
   133  					AccessListRules: []*acl.RuleConfiguration{
   134  						{
   135  							Conditions: []string{
   136  								"match roles authp/admin authp/user",
   137  							},
   138  							Action: "allow stop",
   139  						},
   140  					},
   141  					AuthRedirectDisabled: true,
   142  				},
   143  			},
   144  			want: `{
   145                "config": {
   146                  "authentication_portals": [
   147                    {
   148                      "access_list_configs": [
   149  						{
   150  							"action": "allow stop",
   151  							"comment": "admin role name match",
   152  							"conditions": ["match role authp/admin"]
   153  						},
   154  						{
   155  							"action": "allow stop",
   156  							"comment": "user role name match",
   157  							"conditions": ["match role authp/user"]
   158  						},
   159  						{
   160  							"action": "allow stop",
   161  							"comment": "guest role name match",
   162  							"conditions": ["match role authp/guest"]
   163  						}
   164                      ],
   165                      "identity_stores": [
   166                        "localdb"
   167                      ],
   168                      "name": "myportal",
   169  					"portal_admin_roles": {
   170  						"authp/admin": true
   171  					},
   172  					"portal_user_roles": {
   173  						"authp/user": true
   174  					},
   175  					"portal_guest_roles": {
   176  						"authp/guest": true
   177  					},
   178                      "token_validator_options": {
   179                        "validate_bearer_header": true
   180                      },
   181                      "ui": {
   182                        "theme": "basic"
   183                      }
   184                    }
   185                  ],
   186                  "authorization_policies": [
   187                    {
   188                      "access_list_rules": [
   189                        {
   190                          "action": "allow stop",
   191                          "conditions": [
   192                            "match roles authp/admin authp/user"
   193                          ]
   194                        }
   195                      ],
   196                      "auth_redirect_query_param": "redirect_url",
   197                      "auth_redirect_status_code": 302,
   198                      "auth_url_path": "/auth",
   199                      "disable_auth_redirect": true,
   200                      "name": "mygatekeeper"
   201                    }
   202                  ],
   203                  "credentials": {
   204                    "generic": [
   205                      {
   206                        "name": "foobar",
   207                        "password": "bar",
   208                        "username": "foo"
   209                      }
   210                    ]
   211                  },
   212                  "identity_providers": [
   213                    {
   214                      "kind": "oauth",
   215                      "name": "contoso",
   216                      "params": {
   217                        "authorization_url": "https://localhost/oauth/authorize",
   218                        "base_auth_url": "https://localhost/oauth",
   219                        "client_id": "foo",
   220                        "client_secret": "bar",
   221                        "driver": "generic",
   222                        "jwks_keys": {
   223                          "87329db33bf": "testdata/oauth/87329db33bf_pub.pem"
   224                        },
   225                        "key_verification_disabled": true,
   226                        "realm": "contoso",
   227                        "required_token_fields": [
   228                          "access_token"
   229                        ],
   230                        "response_type": [
   231                          "code"
   232                        ],
   233                        "tls_insecure_skip_verify": true,
   234                        "token_url": "https://localhost/oauth/access_token"
   235                      }
   236                    }
   237                  ],
   238                  "identity_stores": [
   239                    {
   240                      "kind": "local",
   241                      "name": "localdb",
   242                      "params": {
   243                        "path": "` + dbPath + `",
   244                        "realm": "local"
   245                      }
   246                    }
   247                  ],
   248                  "messaging": {
   249                    "email_providers": [
   250                      {
   251                        "address": "localhost",
   252                        "credentials": "foobar",
   253                        "name": "default",
   254                        "protocol": "smtp",
   255                        "sender_email": "root@localhost"
   256                      }
   257                    ]
   258                  }
   259                }
   260  		    }`,
   261  		},
   262  	}
   263  
   264  	for _, tc := range testcases {
   265  		t.Run(tc.name, func(t *testing.T) {
   266  
   267  			cfg := NewConfig()
   268  
   269  			for _, item := range tc.credentials {
   270  				if err := cfg.AddCredential(item); err != nil {
   271  					t.Fatal(err)
   272  				}
   273  			}
   274  
   275  			for _, item := range tc.messaging {
   276  				if err := cfg.AddMessagingProvider(item); err != nil {
   277  					t.Fatal(err)
   278  				}
   279  			}
   280  
   281  			for _, item := range tc.identityStores {
   282  				if err := cfg.AddIdentityStore(item.Name, item.Kind, item.Params); err != nil {
   283  					t.Fatal(err)
   284  				}
   285  			}
   286  
   287  			for _, item := range tc.identityProviders {
   288  				if err := cfg.AddIdentityProvider(item.Name, item.Kind, item.Params); err != nil {
   289  					t.Fatal(err)
   290  				}
   291  			}
   292  
   293  			for _, item := range tc.portals {
   294  				if err := cfg.AddAuthenticationPortal(item); err != nil {
   295  					t.Fatal(err)
   296  				}
   297  			}
   298  
   299  			for _, item := range tc.policies {
   300  				if err := cfg.AddAuthorizationPolicy(item); err != nil {
   301  					t.Fatal(err)
   302  				}
   303  			}
   304  
   305  			server, err := NewServer(cfg, tc.logger)
   306  			if err != nil {
   307  				if !tc.shouldErr {
   308  					t.Fatalf("expected success, got: %v", err)
   309  				}
   310  				if diff := cmp.Diff(err.Error(), tc.err.Error()); diff != "" {
   311  					t.Fatalf("unexpected error: %v, want: %v", err, tc.err)
   312  				}
   313  				return
   314  			}
   315  			if tc.shouldErr {
   316  				t.Fatalf("unexpected success, want: %v", tc.err)
   317  			}
   318  
   319  			got := make(map[string]interface{})
   320  			got["config"] = server.GetConfig()
   321  			want := tests.Unpack(t, tc.want)
   322  
   323  			if diff := cmp.Diff(want, got); diff != "" {
   324  				t.Logf("JSON: %s", tests.UnpackJSON(t, got))
   325  				t.Errorf("NewServer() config mismatch (-want +got):\n%s", diff)
   326  			}
   327  		})
   328  	}
   329  }