github.com/greenpau/go-authcrunch@v1.1.4/internal/tag/tag_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 tag
    16  
    17  import (
    18  	"bufio"
    19  	"fmt"
    20  	"strings"
    21  	"unicode"
    22  
    23  	"github.com/greenpau/go-authcrunch"
    24  	"github.com/greenpau/go-authcrunch/internal/tests"
    25  	"github.com/greenpau/go-authcrunch/internal/testutils"
    26  	"github.com/greenpau/go-authcrunch/pkg/acl"
    27  	"github.com/greenpau/go-authcrunch/pkg/authn"
    28  	authncache "github.com/greenpau/go-authcrunch/pkg/authn/cache"
    29  	"github.com/greenpau/go-authcrunch/pkg/authn/cookie"
    30  	"github.com/greenpau/go-authcrunch/pkg/authn/icons"
    31  	"github.com/greenpau/go-authcrunch/pkg/authn/transformer"
    32  	"github.com/greenpau/go-authcrunch/pkg/authn/ui"
    33  	"github.com/greenpau/go-authcrunch/pkg/authproxy"
    34  	"github.com/greenpau/go-authcrunch/pkg/authz"
    35  	"github.com/greenpau/go-authcrunch/pkg/authz/bypass"
    36  	"github.com/greenpau/go-authcrunch/pkg/authz/cache"
    37  	"github.com/greenpau/go-authcrunch/pkg/authz/injector"
    38  	"github.com/greenpau/go-authcrunch/pkg/authz/options"
    39  	"github.com/greenpau/go-authcrunch/pkg/authz/validator"
    40  	"github.com/greenpau/go-authcrunch/pkg/credentials"
    41  	"github.com/greenpau/go-authcrunch/pkg/identity"
    42  	"github.com/greenpau/go-authcrunch/pkg/identity/qr"
    43  	"github.com/greenpau/go-authcrunch/pkg/idp"
    44  	"github.com/greenpau/go-authcrunch/pkg/idp/oauth"
    45  	"github.com/greenpau/go-authcrunch/pkg/idp/saml"
    46  	"github.com/greenpau/go-authcrunch/pkg/ids"
    47  	"github.com/greenpau/go-authcrunch/pkg/ids/ldap"
    48  	"github.com/greenpau/go-authcrunch/pkg/ids/local"
    49  	"github.com/greenpau/go-authcrunch/pkg/kms"
    50  	"github.com/greenpau/go-authcrunch/pkg/messaging"
    51  	"github.com/greenpau/go-authcrunch/pkg/redirects"
    52  	"github.com/greenpau/go-authcrunch/pkg/registry"
    53  	"github.com/greenpau/go-authcrunch/pkg/requests"
    54  	"github.com/greenpau/go-authcrunch/pkg/sso"
    55  	"github.com/greenpau/go-authcrunch/pkg/tagging"
    56  	"github.com/greenpau/go-authcrunch/pkg/user"
    57  	"github.com/greenpau/go-authcrunch/pkg/util"
    58  	"github.com/greenpau/go-authcrunch/pkg/util/cfg"
    59  
    60  	"os"
    61  	"path/filepath"
    62  	"testing"
    63  )
    64  
    65  func TestTagCompliance(t *testing.T) {
    66  	testcases := []struct {
    67  		name      string
    68  		entry     interface{}
    69  		opts      *Options
    70  		shouldErr bool
    71  		err       error
    72  	}{
    73  		{
    74  			name:  "test sso.KeyInfo struct",
    75  			entry: &sso.KeyInfo{},
    76  			opts: &Options{
    77  				Disabled: true,
    78  			},
    79  		},
    80  		{
    81  			name:  "test sso.SingleSignOnService struct",
    82  			entry: &sso.SingleSignOnService{},
    83  			opts: &Options{
    84  				Disabled: true,
    85  			},
    86  		},
    87  		{
    88  			name:  "test sso.EntityDescriptor struct",
    89  			entry: &sso.EntityDescriptor{},
    90  			opts: &Options{
    91  				Disabled: true,
    92  			},
    93  		},
    94  		{
    95  			name:  "test sso.X509Data struct",
    96  			entry: &sso.X509Data{},
    97  			opts: &Options{
    98  				Disabled: true,
    99  			},
   100  		},
   101  		{
   102  			name:  "test sso.IDPEntityDescriptor struct",
   103  			entry: &sso.IDPEntityDescriptor{},
   104  			opts: &Options{
   105  				Disabled: true,
   106  			},
   107  		},
   108  		{
   109  			name:  "test sso.Service struct",
   110  			entry: &sso.Service{},
   111  			opts: &Options{
   112  				Disabled: true,
   113  			},
   114  		},
   115  		{
   116  			name:  "test sso.IDPSSODescriptor struct",
   117  			entry: &sso.IDPSSODescriptor{},
   118  			opts: &Options{
   119  				Disabled: true,
   120  			},
   121  		},
   122  		{
   123  			name:  "test sso.KeyDescriptor struct",
   124  			entry: &sso.KeyDescriptor{},
   125  			opts: &Options{
   126  				Disabled: true,
   127  			},
   128  		},
   129  		{
   130  			name:  "test sso.Provider struct",
   131  			entry: &sso.Provider{},
   132  			opts:  &Options{},
   133  		},
   134  		{
   135  			name:  "test sso.SingleSignOnProviderConfig struct",
   136  			entry: &sso.SingleSignOnProviderConfig{},
   137  			opts:  &Options{},
   138  		},
   139  		{
   140  			name:  "test sso.Request struct",
   141  			entry: &sso.Request{},
   142  			opts:  &Options{},
   143  		},
   144  		{
   145  			name:  "test ui.NavigationItem struct",
   146  			entry: &ui.NavigationItem{},
   147  			opts:  &Options{},
   148  		},
   149  		{
   150  			name:  "test requests.IdentityTokenCookie struct",
   151  			entry: &requests.IdentityTokenCookie{},
   152  			opts:  &Options{},
   153  		},
   154  		{
   155  			name:  "test icons.LoginIcon struct",
   156  			entry: &icons.LoginIcon{},
   157  			opts:  &Options{},
   158  		},
   159  		{
   160  			name:  "test registry.LocaUserRegistry struct",
   161  			entry: &registry.LocaUserRegistry{},
   162  			opts:  &Options{},
   163  		},
   164  		{
   165  			name:  "test messaging.FileProvider struct",
   166  			entry: &messaging.FileProvider{},
   167  			opts:  &Options{},
   168  		},
   169  		{
   170  			name:  "test messaging.FileProviderSendInput struct",
   171  			entry: &messaging.FileProviderSendInput{},
   172  			opts:  &Options{},
   173  		},
   174  		{
   175  			name:  "test messaging.EmailProviderSendInput struct",
   176  			entry: &messaging.EmailProviderSendInput{},
   177  			opts:  &Options{},
   178  		},
   179  		{
   180  			name:  "test authn.PortalParameters struct",
   181  			entry: &authn.PortalParameters{},
   182  			opts: &Options{
   183  				AllowFieldMismatch: true,
   184  				AllowedFields: map[string]interface{}{
   185  					"sso_providers": true,
   186  				},
   187  			},
   188  		},
   189  		{
   190  			name:  "test idp.IdentityProviderConfig struct",
   191  			entry: &idp.IdentityProviderConfig{},
   192  			opts:  &Options{},
   193  		},
   194  		{
   195  			name:  "test ids.IdentityStoreConfig struct",
   196  			entry: &ids.IdentityStoreConfig{},
   197  			opts:  &Options{},
   198  		},
   199  		{
   200  			name:  "test util.Browser struct",
   201  			entry: &util.Browser{},
   202  			opts:  &Options{},
   203  		},
   204  		{
   205  			name:  "test authn.APIConfig struct",
   206  			entry: &authn.APIConfig{},
   207  			opts:  &Options{},
   208  		},
   209  		{
   210  			name:  "test cookie.DomainConfig struct",
   211  			entry: &cookie.DomainConfig{},
   212  			opts:  &Options{},
   213  		},
   214  		{
   215  			name:  "test registry.RegistrationCache struct",
   216  			entry: &registry.RegistrationCache{},
   217  			opts:  &Options{},
   218  		},
   219  		{
   220  			name:  "test registry.RegistrationCacheEntry struct",
   221  			entry: &registry.RegistrationCacheEntry{},
   222  			opts:  &Options{},
   223  		},
   224  		{
   225  			name:  "test messaging.EmailProvider struct",
   226  			entry: &messaging.EmailProvider{},
   227  			opts:  &Options{},
   228  		},
   229  		{
   230  			name:  "test messaging.Config struct",
   231  			entry: &messaging.Config{},
   232  			opts:  &Options{},
   233  		},
   234  		{
   235  			name:  "test requests.Query struct",
   236  			entry: &requests.Query{},
   237  			opts:  &Options{},
   238  		},
   239  		{
   240  			name:  "test requests.User struct",
   241  			entry: &requests.User{},
   242  			opts:  &Options{},
   243  		},
   244  		{
   245  			name:  "test requests.Key struct",
   246  			entry: &requests.Key{},
   247  			opts:  &Options{},
   248  		},
   249  		{
   250  			name:  "test requests.MfaToken struct",
   251  			entry: &requests.MfaToken{},
   252  			opts:  &Options{},
   253  		},
   254  		{
   255  			name:  "test requests.Request struct",
   256  			entry: &requests.Request{},
   257  			opts:  &Options{},
   258  		},
   259  		{
   260  			name:  "test requests.Upstream struct",
   261  			entry: &requests.Upstream{},
   262  			opts:  &Options{},
   263  		},
   264  		{
   265  			name:  "test requests.Flags struct",
   266  			entry: &requests.Flags{},
   267  			opts:  &Options{},
   268  		},
   269  		{
   270  			name:  "test requests.Response struct",
   271  			entry: &requests.Response{},
   272  			opts:  &Options{},
   273  		},
   274  		{
   275  			name:  "test requests.Sandbox struct",
   276  			entry: &requests.Sandbox{},
   277  			opts:  &Options{},
   278  		},
   279  		{
   280  			name:  "test requests.WebAuthn struct",
   281  			entry: &requests.WebAuthn{},
   282  			opts:  &Options{},
   283  		},
   284  		{
   285  			name:  "test public key",
   286  			entry: &identity.PublicKey{},
   287  		},
   288  		{
   289  			name:  "test AttestationObject struct",
   290  			entry: &identity.AttestationObject{},
   291  			opts: &Options{
   292  				DisableTagMismatch: true,
   293  			},
   294  		},
   295  		{
   296  			name:  "test AttestationStatement struct",
   297  			entry: &identity.AttestationStatement{},
   298  			opts: &Options{
   299  				DisableTagMismatch: true,
   300  			},
   301  		},
   302  		{
   303  			name:  "test AuthData struct",
   304  			entry: &identity.AuthData{},
   305  			opts: &Options{
   306  				DisableTagMismatch: true,
   307  			},
   308  		},
   309  		{
   310  			name:  "test ClientData struct",
   311  			entry: &identity.ClientData{},
   312  			opts: &Options{
   313  				DisableTagMismatch: true,
   314  			},
   315  		},
   316  		{
   317  			name:  "test CredentialData struct",
   318  			entry: &identity.CredentialData{},
   319  			opts: &Options{
   320  				DisableTagMismatch: true,
   321  			},
   322  		},
   323  		{
   324  			name:  "test CreditCard struct",
   325  			entry: &identity.CreditCard{},
   326  		},
   327  		{
   328  			name:  "test CreditCardAssociation struct",
   329  			entry: &identity.CreditCardAssociation{},
   330  		},
   331  		{
   332  			name:  "test CreditCardIssuer struct",
   333  			entry: &identity.CreditCardIssuer{},
   334  		},
   335  		{
   336  			name:  "test Database struct",
   337  			entry: &identity.Database{},
   338  		},
   339  		{
   340  			name:  "test Device struct",
   341  			entry: &identity.Device{},
   342  		},
   343  		{
   344  			name:  "test EmailAddress struct",
   345  			entry: &identity.EmailAddress{},
   346  		},
   347  		{
   348  			name:  "test Handle struct",
   349  			entry: &identity.Handle{},
   350  		},
   351  		{
   352  			name:  "test Image struct",
   353  			entry: &identity.Image{},
   354  		},
   355  		{
   356  			name:  "test Location struct",
   357  			entry: &identity.Location{},
   358  		},
   359  		{
   360  			name:  "test LockoutState struct",
   361  			entry: &identity.LockoutState{},
   362  		},
   363  		{
   364  			name:  "test MfaDevice struct",
   365  			entry: &identity.MfaDevice{},
   366  		},
   367  		{
   368  			name:  "test MfaToken struct",
   369  			entry: &identity.MfaToken{},
   370  		},
   371  		{
   372  			name:  "test MfaTokenBundle struct",
   373  			entry: &identity.MfaTokenBundle{},
   374  		},
   375  		{
   376  			name:  "test Name struct",
   377  			entry: &identity.Name{},
   378  		},
   379  		{
   380  			name:  "test Organization struct",
   381  			entry: &identity.Organization{},
   382  		},
   383  		{
   384  			name:  "test Password struct",
   385  			entry: &identity.Password{},
   386  		},
   387  		{
   388  			name:  "test PublicKey struct",
   389  			entry: &identity.PublicKey{},
   390  		},
   391  		{
   392  			name:  "test PublicKeyBundle struct",
   393  			entry: &identity.PublicKeyBundle{},
   394  		},
   395  		{
   396  			name:  "test Registration struct",
   397  			entry: &identity.Registration{},
   398  		},
   399  		{
   400  			name:  "test Request struct",
   401  			entry: &requests.Request{},
   402  		},
   403  		{
   404  			name:  "test Role struct",
   405  			entry: &identity.Role{},
   406  		},
   407  		{
   408  			name:  "test User struct",
   409  			entry: &identity.User{},
   410  		},
   411  		{
   412  			name:  "test Policy struct",
   413  			entry: &identity.Policy{},
   414  		},
   415  		{
   416  			name:  "test UserPolicy struct",
   417  			entry: &identity.UserPolicy{},
   418  			opts: &Options{
   419  				DisableTagOnEmpty: true,
   420  			},
   421  		},
   422  		{
   423  			name:  "test PasswordPolicy struct",
   424  			entry: &identity.PasswordPolicy{},
   425  			opts: &Options{
   426  				DisableTagOnEmpty: true,
   427  			},
   428  		},
   429  		{
   430  			name:  "test WebAuthnRegisterRequest struct",
   431  			entry: &identity.WebAuthnRegisterRequest{},
   432  			opts: &Options{
   433  				DisableTagMismatch: true,
   434  			},
   435  		},
   436  		{
   437  			name:  "test identity.UserMetadata struct",
   438  			entry: &identity.UserMetadata{},
   439  			opts:  &Options{},
   440  		},
   441  		{
   442  			name:  "test identity.UserMetadataBundle struct",
   443  			entry: &identity.UserMetadataBundle{},
   444  			opts:  &Options{},
   445  		},
   446  		{
   447  			name:  "test qr.Code struct",
   448  			entry: &qr.Code{},
   449  			opts:  &Options{},
   450  		},
   451  		{
   452  			name:  "test identity.WebAuthnAuthenticateRequest struct",
   453  			entry: &identity.WebAuthnAuthenticateRequest{},
   454  			opts:  &Options{},
   455  		},
   456  		{
   457  			name:  "test identity.APIKeyBundle struct",
   458  			entry: &identity.APIKeyBundle{},
   459  			opts:  &Options{},
   460  		},
   461  		{
   462  			name:  "test identity.APIKey struct",
   463  			entry: &identity.APIKey{},
   464  			opts:  &Options{},
   465  		},
   466  		{
   467  			name:  "test authn.PortalConfig struct",
   468  			entry: &authn.PortalConfig{},
   469  			opts: &Options{
   470  				AllowFieldMismatch: true,
   471  				AllowedFields: map[string]interface{}{
   472  					"sso_providers": true,
   473  				},
   474  			},
   475  		},
   476  		{
   477  			name:  "test requests.AuthorizationRequest struct",
   478  			entry: &requests.AuthorizationRequest{},
   479  			opts:  &Options{},
   480  		},
   481  		{
   482  			name:  "test ui.Link struct",
   483  			entry: &ui.Link{},
   484  			opts:  &Options{},
   485  		},
   486  		{
   487  			name:  "test ui.Args struct",
   488  			entry: &ui.Args{},
   489  			opts:  &Options{},
   490  		},
   491  		{
   492  			name:  "test requests.AuthorizationResponse struct",
   493  			entry: &requests.AuthorizationResponse{},
   494  			opts: &Options{
   495  				Disabled: true,
   496  			},
   497  		},
   498  		{
   499  			name:  "test cache.SessionCache struct",
   500  			entry: &authncache.SessionCache{},
   501  			opts:  &Options{},
   502  		},
   503  		{
   504  			name:  "test ui.Template struct",
   505  			entry: &ui.Template{},
   506  			opts:  &Options{},
   507  		},
   508  		{
   509  			name:  "test authproxy.BasicAuthConfig struct",
   510  			entry: &authproxy.BasicAuthConfig{},
   511  			opts:  &Options{},
   512  		},
   513  		{
   514  			name:  "test user.Claims struct",
   515  			entry: &user.Claims{},
   516  			opts: &Options{
   517  				DisableTagMismatch: true,
   518  			},
   519  		},
   520  		{
   521  			name:  "test acl.RuleConfiguration struct",
   522  			entry: &acl.RuleConfiguration{},
   523  			opts:  &Options{},
   524  		},
   525  		{
   526  			name:  "test ldap.Authenticator struct",
   527  			entry: &ldap.Authenticator{},
   528  			opts:  &Options{},
   529  		},
   530  		{
   531  			name:  "test kms.CryptoKeyOperator struct",
   532  			entry: &kms.CryptoKeyOperator{},
   533  			opts:  &Options{},
   534  		},
   535  		{
   536  			name:  "test cache.SandboxCacheEntry struct",
   537  			entry: &authncache.SandboxCacheEntry{},
   538  			opts:  &Options{},
   539  		},
   540  		{
   541  			name:  "test local.Config struct",
   542  			entry: &local.Config{},
   543  			opts:  &Options{},
   544  		},
   545  		{
   546  			name:  "test local.User struct",
   547  			entry: &local.User{},
   548  			opts:  &Options{},
   549  		},
   550  		{
   551  			name:  "test credentials.Config struct",
   552  			entry: &credentials.Config{},
   553  			opts:  &Options{},
   554  		},
   555  		{
   556  			name:  "test registry.UserRegistryConfig struct",
   557  			entry: &registry.UserRegistryConfig{},
   558  			opts: &Options{
   559  				AllowFieldMismatch: true,
   560  				AllowedFields: map[string]interface{}{
   561  					"require_domain_mx": true,
   562  				},
   563  			},
   564  		},
   565  		{
   566  			name:  "test ui.UserRealm struct",
   567  			entry: &ui.UserRealm{},
   568  			opts:  &Options{},
   569  		},
   570  		{
   571  			name:  "test ui.Parameters struct",
   572  			entry: &ui.Parameters{},
   573  			opts:  &Options{},
   574  		},
   575  		{
   576  			name:  "test ui.StaticAsset struct",
   577  			entry: &ui.StaticAsset{},
   578  			opts:  &Options{},
   579  		},
   580  		{
   581  			name:  "test local.Backend struct",
   582  			entry: &local.IdentityStore{},
   583  			opts:  &Options{},
   584  		},
   585  		{
   586  			name:  "test local.Authenticator struct",
   587  			entry: &local.Authenticator{},
   588  			opts:  &Options{},
   589  		},
   590  		{
   591  			name:  "test options.TokenGrantorOptions struct",
   592  			entry: &options.TokenGrantorOptions{},
   593  			opts:  &Options{},
   594  		},
   595  		{
   596  			name:  "test oauth.Config struct",
   597  			entry: &oauth.Config{},
   598  			opts: &Options{
   599  				AllowFieldMismatch: true,
   600  				AllowedFields: map[string]interface{}{
   601  					"user_roles": true,
   602  				},
   603  			},
   604  		},
   605  		{
   606  			name:  "test cookie.Factory struct",
   607  			entry: &cookie.Factory{},
   608  			opts:  &Options{},
   609  		},
   610  		{
   611  			name:  "test user.Checkpoint struct",
   612  			entry: &user.Checkpoint{},
   613  			opts:  &Options{},
   614  		},
   615  		{
   616  			name:  "test transformer.Factory struct",
   617  			entry: &transformer.Factory{},
   618  			opts:  &Options{},
   619  		},
   620  		{
   621  			name:  "test user.AccessListClaim struct",
   622  			entry: &user.AccessListClaim{},
   623  			opts:  &Options{},
   624  		},
   625  		{
   626  			name:  "test testutils.InjectedTestToken struct",
   627  			entry: &testutils.InjectedTestToken{},
   628  			opts:  &Options{},
   629  		},
   630  		{
   631  			name:  "test kms.CryptoKey struct",
   632  			entry: &kms.CryptoKey{},
   633  			opts:  &Options{},
   634  		},
   635  		{
   636  			name:  "test cache.SandboxCache struct",
   637  			entry: &authncache.SandboxCache{},
   638  			opts:  &Options{},
   639  		},
   640  		{
   641  			name:  "test cookie.Config struct",
   642  			entry: &cookie.Config{},
   643  			opts:  &Options{},
   644  		},
   645  		{
   646  			name:  "test ldap.UserAttributes struct",
   647  			entry: &ldap.UserAttributes{},
   648  			opts:  &Options{},
   649  		},
   650  		{
   651  			name:  "test ui.StaticAssetLibrary struct",
   652  			entry: &ui.StaticAssetLibrary{},
   653  			opts:  &Options{},
   654  		},
   655  		{
   656  			name:  "test credentials.Generic struct",
   657  			entry: &credentials.Generic{},
   658  			opts:  &Options{},
   659  		},
   660  		{
   661  			name:  "test oauth.Backend struct",
   662  			entry: &oauth.IdentityProvider{},
   663  			opts:  &Options{},
   664  		},
   665  		{
   666  			name:  "test authproxy.Config struct",
   667  			entry: &authproxy.Config{},
   668  			opts:  &Options{},
   669  		},
   670  		{
   671  			name:  "test kms.CryptoKeyStore struct",
   672  			entry: &kms.CryptoKeyStore{},
   673  			opts:  &Options{},
   674  		},
   675  		{
   676  			name:  "test kms.CryptoKeyConfig struct",
   677  			entry: &kms.CryptoKeyConfig{},
   678  			opts: &Options{
   679  				AllowFieldMismatch: true,
   680  				AllowedFields: map[string]interface{}{
   681  					"token_secret":      true,
   682  					"token_sign_method": true,
   683  					"token_eval_expr":   true,
   684  				},
   685  			},
   686  		},
   687  		{
   688  			name:  "test cache.SessionCacheEntry struct",
   689  			entry: &authncache.SessionCacheEntry{},
   690  			opts:  &Options{},
   691  		},
   692  		{
   693  			name:  "test saml.Backend struct",
   694  			entry: &saml.IdentityProvider{},
   695  			opts:  &Options{},
   696  		},
   697  		{
   698  			name:  "test transformer.Config struct",
   699  			entry: &transformer.Config{},
   700  			opts:  &Options{},
   701  		},
   702  		{
   703  			name:  "test authcrunch.Config struct",
   704  			entry: &authcrunch.Config{},
   705  			opts: &Options{
   706  				AllowFieldMismatch: true,
   707  				AllowedFields: map[string]interface{}{
   708  					"auth_portal_configs":  true,
   709  					"authz_policy_configs": true,
   710  					"sso_providers":        true,
   711  				},
   712  			},
   713  		},
   714  		{
   715  			name:  "test cache.TokenCache struct",
   716  			entry: &cache.TokenCache{},
   717  			opts:  &Options{},
   718  		},
   719  		{
   720  			name:  "test ui.Factory struct",
   721  			entry: &ui.Factory{},
   722  			opts:  &Options{},
   723  		},
   724  		{
   725  			name:  "test authproxy.Response struct",
   726  			entry: &authproxy.Response{},
   727  			opts:  &Options{},
   728  		},
   729  		{
   730  			name:  "test user.Authenticator struct",
   731  			entry: &user.Authenticator{},
   732  			opts:  &Options{},
   733  		},
   734  		{
   735  			name:  "test cfg.ArgRule struct",
   736  			entry: &cfg.ArgRule{},
   737  			opts:  &Options{},
   738  		},
   739  		{
   740  			name:  "test oauth.JwksKey struct",
   741  			entry: &oauth.JwksKey{},
   742  			opts: &Options{
   743  				DisableTagMismatch: true,
   744  			},
   745  		},
   746  		{
   747  			name:  "test authproxy.Request struct",
   748  			entry: &authproxy.Request{},
   749  			opts:  &Options{},
   750  		},
   751  		{
   752  			name:  "test kms.CryptoKeyTokenOperator struct",
   753  			entry: &kms.CryptoKeyTokenOperator{},
   754  			opts:  &Options{},
   755  		},
   756  		{
   757  			name:  "test options.TokenValidatorOptions struct",
   758  			entry: &options.TokenValidatorOptions{},
   759  			opts:  &Options{},
   760  		},
   761  		{
   762  			name:  "test ldap.Backend struct",
   763  			entry: &ldap.IdentityStore{},
   764  			opts:  &Options{},
   765  		},
   766  		{
   767  			name:  "test validator.TokenValidator struct",
   768  			entry: &validator.TokenValidator{},
   769  			opts:  &Options{},
   770  		},
   771  		{
   772  			name:  "test saml.Config struct",
   773  			entry: &saml.Config{},
   774  			opts: &Options{
   775  				AllowFieldMismatch: true,
   776  				AllowedFields: map[string]interface{}{
   777  					"acs_urls": true,
   778  				},
   779  			},
   780  		},
   781  		{
   782  			name:  "test ldap.AuthServer struct",
   783  			entry: &ldap.AuthServer{},
   784  			opts:  &Options{},
   785  		},
   786  		{
   787  			name:  "test user.User struct",
   788  			entry: &user.User{},
   789  			opts:  &Options{},
   790  		},
   791  		{
   792  			name:  "test ldap.UserGroup struct",
   793  			entry: &ldap.UserGroup{},
   794  			opts: &Options{
   795  				AllowFieldMismatch: true,
   796  				AllowedFields: map[string]interface{}{
   797  					"dn": true,
   798  				},
   799  			},
   800  		},
   801  		{
   802  			name:  "test authproxy.APIKeyAuthConfig struct",
   803  			entry: &authproxy.APIKeyAuthConfig{},
   804  			opts:  &Options{},
   805  		},
   806  		{
   807  			name:  "test ldap.Config struct",
   808  			entry: &ldap.Config{},
   809  			opts:  &Options{},
   810  		},
   811  		{
   812  			name:  "test acl.AccessList struct",
   813  			entry: &acl.AccessList{},
   814  			opts:  &Options{},
   815  		},
   816  		{
   817  			name:  "test authz.PolicyConfig struct",
   818  			entry: &authz.PolicyConfig{},
   819  			opts: &Options{
   820  				AllowFieldMismatch: true,
   821  				AllowedFields: map[string]interface{}{
   822  					"disable_auth_redirect":       true,
   823  					"disable_auth_redirect_query": true,
   824  					"auth_redirect_query_param":   true,
   825  				},
   826  			},
   827  		},
   828  		{
   829  			name:  "test bypass.Config struct",
   830  			entry: &bypass.Config{},
   831  			opts:  &Options{},
   832  		},
   833  		{
   834  			name:  "test injector.Config struct",
   835  			entry: &injector.Config{},
   836  			opts:  &Options{},
   837  		},
   838  		{
   839  			name:  "test authn.AuthRequest struct",
   840  			entry: &authn.AuthRequest{},
   841  			opts:  &Options{},
   842  		},
   843  		{
   844  			name:  "test authn.AccessDeniedResponse struct",
   845  			entry: &authn.AccessDeniedResponse{},
   846  			opts:  &Options{},
   847  		},
   848  		{
   849  			name:  "test authn.Portal struct",
   850  			entry: &authn.Portal{},
   851  			opts:  &Options{},
   852  		},
   853  		{
   854  			name:  "test authn.AuthResponse struct",
   855  			entry: &authn.AuthResponse{},
   856  			opts:  &Options{},
   857  		},
   858  		{
   859  			name:  "test authcrunch.Server struct",
   860  			entry: &authcrunch.Server{},
   861  			opts:  &Options{},
   862  		},
   863  		{
   864  			name:  "test requests.RedirectResponse struct",
   865  			entry: &requests.RedirectResponse{},
   866  			opts:  &Options{},
   867  		},
   868  		{
   869  			name:  "test authz.Gatekeeper struct",
   870  			entry: &authz.Gatekeeper{},
   871  			opts:  &Options{},
   872  		},
   873  		{
   874  			name:  "test requests.AuthorizationToken struct",
   875  			entry: &requests.AuthorizationToken{},
   876  			opts:  &Options{},
   877  		},
   878  		{
   879  			name:  "test redirects.RedirectURIMatchConfig struct",
   880  			entry: &redirects.RedirectURIMatchConfig{},
   881  			opts:  &Options{},
   882  		},
   883  		{
   884  			name:  "test tagging.Tag struct",
   885  			entry: &tagging.Tag{},
   886  			opts:  &Options{},
   887  		},
   888  	}
   889  
   890  	for _, tc := range testcases {
   891  		t.Run(tc.name, func(t *testing.T) {
   892  			msgs, err := GetTagCompliance(tc.entry, tc.opts)
   893  			if tests.EvalErrWithLog(t, err, nil, tc.shouldErr, tc.err, msgs) {
   894  				return
   895  			}
   896  		})
   897  	}
   898  }
   899  
   900  func TestStructTagCompliance(t *testing.T) {
   901  	var files []string
   902  	structMap := make(map[string]bool)
   903  	walkFn := func(path string, fileInfo os.FileInfo, err error) error {
   904  		if err != nil {
   905  			return err
   906  		}
   907  		if fileInfo.IsDir() {
   908  			return nil
   909  		}
   910  		fileName := filepath.Base(path)
   911  		fileExt := filepath.Ext(fileName)
   912  		if fileExt != ".go" {
   913  			return nil
   914  		}
   915  		if strings.Contains(fileName, "_test.go") {
   916  			return nil
   917  		}
   918  		if strings.Contains(path, "/tag/") || strings.Contains(path, "/errors/") {
   919  			return nil
   920  		}
   921  		// t.Logf("%s %d", path, fileInfo.Size())
   922  		files = append(files, path)
   923  		return nil
   924  	}
   925  	if err := filepath.Walk("../../", walkFn); err != nil {
   926  		t.Error(err)
   927  	}
   928  
   929  	excludedFiles := []string{
   930  		"authn/ui/content.go",
   931  		"cmd/authdbctl/user.go",
   932  		"cmd/authdbctl/config.go",
   933  	}
   934  
   935  	for _, fp := range files {
   936  		// t.Logf("file %s", fp)
   937  		var skip bool
   938  		for _, excludedFile := range excludedFiles {
   939  			if strings.HasSuffix(fp, excludedFile) {
   940  				skip = true
   941  				break
   942  			}
   943  		}
   944  		if skip {
   945  			continue
   946  		}
   947  
   948  		var pkgFound bool
   949  		var pkgName string
   950  		fh, _ := os.Open(fp)
   951  		defer fh.Close()
   952  		scanner := bufio.NewScanner(fh)
   953  		for scanner.Scan() {
   954  			line := strings.TrimSpace(scanner.Text())
   955  			if strings.HasPrefix(line, "package ") {
   956  				pkgFound = true
   957  				pkgName = strings.Split(line, " ")[1]
   958  				// t.Logf("package %s", pkgName)
   959  				continue
   960  			}
   961  			if !pkgFound {
   962  				continue
   963  			}
   964  			if strings.HasPrefix(line, "type") && strings.Contains(line, "struct") {
   965  				structName := strings.Split(line, " ")[1]
   966  				// t.Logf("%s.%s", pkgName, structName)
   967  				if !unicode.IsUpper(rune(structName[0])) {
   968  					// Skip unexported structs.
   969  					continue
   970  				}
   971  				structMap[pkgName+"."+structName] = false
   972  			}
   973  
   974  			//fmt.Println(scanner.Text())
   975  		}
   976  		if err := scanner.Err(); err != nil {
   977  			t.Errorf("failed reading %q: %v", fp, err)
   978  		}
   979  	}
   980  
   981  	fp := "../../internal/tag/tag_test.go"
   982  	fh, _ := os.Open(fp)
   983  	defer fh.Close()
   984  	scanner := bufio.NewScanner(fh)
   985  	for scanner.Scan() {
   986  		line := strings.TrimSpace(scanner.Text())
   987  		for k := range structMap {
   988  			if strings.Contains(line, k+"{}") {
   989  				structMap[k] = true
   990  			}
   991  		}
   992  	}
   993  	if err := scanner.Err(); err != nil {
   994  		t.Errorf("failed reading %q: %v", fp, err)
   995  	}
   996  
   997  	if len(structMap) > 0 {
   998  		var msgs []string
   999  		for k, v := range structMap {
  1000  			if v == false {
  1001  				t.Logf("Found struct %s", k)
  1002  				msgs = append(msgs, fmt.Sprintf("{\nname: \"test %s struct\",\nentry: &%s{},\nopts: &Options{},\n},", k, k))
  1003  			}
  1004  		}
  1005  		if len(msgs) > 0 {
  1006  			t.Logf("Add the following tests:\n" + strings.Join(msgs, "\n"))
  1007  			t.Fatal("Fix above structs")
  1008  		}
  1009  	}
  1010  }