github.com/greenpau/go-authcrunch@v1.1.4/server.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 "encoding/json" 19 "fmt" 20 21 "github.com/greenpau/go-authcrunch/pkg/authn" 22 "github.com/greenpau/go-authcrunch/pkg/authproxy" 23 "github.com/greenpau/go-authcrunch/pkg/authz" 24 "github.com/greenpau/go-authcrunch/pkg/errors" 25 "github.com/greenpau/go-authcrunch/pkg/idp" 26 "github.com/greenpau/go-authcrunch/pkg/ids" 27 "github.com/greenpau/go-authcrunch/pkg/registry" 28 "github.com/greenpau/go-authcrunch/pkg/sso" 29 "go.uber.org/zap" 30 ) 31 32 type refMap struct { 33 portals map[string]*authn.Portal 34 gatekeepers map[string]*authz.Gatekeeper 35 identityStores map[string]ids.IdentityStore 36 identityProviders map[string]idp.IdentityProvider 37 ssoProviders map[string]sso.SingleSignOnProvider 38 userRegistries map[string]registry.UserRegistry 39 } 40 41 // Server represents AAA SF server. 42 type Server struct { 43 config *Config 44 portals []*authn.Portal 45 gatekeepers []*authz.Gatekeeper 46 identityStores []ids.IdentityStore 47 identityProviders []idp.IdentityProvider 48 ssoProviders []sso.SingleSignOnProvider 49 userRegistries []registry.UserRegistry 50 nameRefs refMap 51 realmRefs refMap 52 logger *zap.Logger 53 } 54 55 func newRefMap() refMap { 56 return refMap{ 57 portals: make(map[string]*authn.Portal), 58 gatekeepers: make(map[string]*authz.Gatekeeper), 59 identityStores: make(map[string]ids.IdentityStore), 60 identityProviders: make(map[string]idp.IdentityProvider), 61 ssoProviders: make(map[string]sso.SingleSignOnProvider), 62 userRegistries: make(map[string]registry.UserRegistry), 63 } 64 } 65 66 // NewServer returns an instance of Server. 67 func NewServer(config *Config, logger *zap.Logger) (*Server, error) { 68 var authenticators []authproxy.Authenticator 69 if err := config.Validate(); err != nil { 70 return nil, err 71 } 72 73 srv := &Server{ 74 config: config, 75 logger: logger, 76 nameRefs: newRefMap(), 77 realmRefs: newRefMap(), 78 } 79 80 for _, cfg := range config.IdentityProviders { 81 provider, err := idp.NewIdentityProvider(cfg, logger) 82 if err != nil { 83 return nil, errors.ErrNewServer.WithArgs("failed initializing identity provider", err) 84 } 85 if _, exists := srv.nameRefs.identityProviders[provider.GetName()]; exists { 86 return nil, errors.ErrNewServer.WithArgs("duplicate identity provider name", provider.GetName()) 87 } 88 if _, exists := srv.realmRefs.identityProviders[provider.GetRealm()]; exists { 89 return nil, errors.ErrNewServer.WithArgs("duplicate identity provider realm", provider.GetRealm()) 90 } 91 if err := provider.Configure(); err != nil { 92 return nil, errors.ErrNewServer.WithArgs("failed configuring identity provider", err) 93 } 94 srv.nameRefs.identityProviders[provider.GetName()] = provider 95 srv.realmRefs.identityProviders[provider.GetRealm()] = provider 96 srv.identityProviders = append(srv.identityProviders, provider) 97 } 98 99 for _, cfg := range config.IdentityStores { 100 store, err := ids.NewIdentityStore(cfg, logger) 101 if err != nil { 102 return nil, errors.ErrNewServer.WithArgs("failed initializing identity store", err) 103 } 104 if _, exists := srv.nameRefs.identityStores[store.GetName()]; exists { 105 return nil, errors.ErrNewServer.WithArgs("duplicate identity store name", store.GetName()) 106 } 107 if _, exists := srv.realmRefs.identityStores[store.GetRealm()]; exists { 108 return nil, errors.ErrNewServer.WithArgs("duplicate identity store realm", store.GetRealm()) 109 } 110 if err := store.Configure(); err != nil { 111 return nil, errors.ErrNewServer.WithArgs("failed configuring identity store", err) 112 } 113 srv.nameRefs.identityStores[store.GetName()] = store 114 srv.realmRefs.identityStores[store.GetRealm()] = store 115 srv.identityStores = append(srv.identityStores, store) 116 } 117 118 for _, cfg := range config.SingleSignOnProviders { 119 provider, err := sso.NewSingleSignOnProvider(cfg, logger) 120 if err != nil { 121 return nil, errors.ErrNewServer.WithArgs("failed initializing sso provider", err) 122 } 123 if _, exists := srv.nameRefs.ssoProviders[provider.GetName()]; exists { 124 return nil, errors.ErrNewServer.WithArgs("duplicate sso provider name", provider.GetName()) 125 } 126 if err := provider.Configure(); err != nil { 127 return nil, errors.ErrNewServer.WithArgs("failed configuring sso provider", err) 128 } 129 srv.nameRefs.ssoProviders[provider.GetName()] = provider 130 srv.ssoProviders = append(srv.ssoProviders, provider) 131 } 132 133 for _, cfg := range config.UserRegistries { 134 userRegistry, err := registry.NewUserRegistry(cfg, logger) 135 if err != nil { 136 return nil, errors.ErrNewServer.WithArgs("failed initializing user registry", err) 137 } 138 if _, exists := srv.nameRefs.userRegistries[userRegistry.GetName()]; exists { 139 return nil, errors.ErrNewServer.WithArgs("duplicate user registry name", userRegistry.GetName()) 140 } 141 srv.nameRefs.userRegistries[userRegistry.GetName()] = userRegistry 142 srv.userRegistries = append(srv.userRegistries, userRegistry) 143 } 144 145 for _, cfg := range config.AuthenticationPortals { 146 params := authn.PortalParameters{ 147 Config: cfg, 148 Logger: logger, 149 IdentityStores: srv.identityStores, 150 IdentityProviders: srv.identityProviders, 151 SingleSignOnProviders: srv.ssoProviders, 152 } 153 154 portal, err := authn.NewPortal(params) 155 if err != nil { 156 return nil, err 157 } 158 159 if _, exists := srv.nameRefs.portals[cfg.Name]; exists { 160 return nil, errors.ErrNewServer.WithArgs("duplicate authentication portal name", cfg.Name) 161 } 162 163 srv.nameRefs.portals[cfg.Name] = portal 164 srv.portals = append(srv.portals, portal) 165 authenticators = append(authenticators, portal) 166 } 167 168 for _, cfg := range config.AuthorizationPolicies { 169 gatekeeper, err := authz.NewGatekeeper(cfg, logger) 170 if err != nil { 171 return nil, err 172 } 173 174 if _, exists := srv.nameRefs.gatekeepers[cfg.Name]; exists { 175 return nil, errors.ErrNewServer.WithArgs("duplicate authorization policy name", cfg.Name) 176 } 177 srv.nameRefs.gatekeepers[cfg.Name] = gatekeeper 178 srv.gatekeepers = append(srv.gatekeepers, gatekeeper) 179 } 180 181 for _, gatekeeper := range srv.gatekeepers { 182 if err := gatekeeper.AddAuthenticators(authenticators); err != nil { 183 return nil, err 184 } 185 } 186 187 for _, portal := range srv.portals { 188 enabledIdentityStores := portal.GetIdentityStoreNames() 189 for _, userRegistry := range srv.userRegistries { 190 if _, exists := enabledIdentityStores[userRegistry.GetIdentityStoreName()]; !exists { 191 continue 192 } 193 if err := portal.AddUserRegistry(userRegistry); err != nil { 194 return nil, errors.ErrNewServer.WithArgs("failed adding registry to portal", err) 195 } 196 } 197 } 198 199 return srv, nil 200 } 201 202 // GetConfig returns Server configuration. 203 func (srv *Server) GetConfig() map[string]interface{} { 204 var m map[string]interface{} 205 b, _ := json.Marshal(srv.config) 206 json.Unmarshal(b, &m) 207 return m 208 } 209 210 // GetPortalByName returns an instance of authn.Portal based on its name. 211 func (srv *Server) GetPortalByName(s string) (*authn.Portal, error) { 212 if portal, exists := srv.nameRefs.portals[s]; exists { 213 return portal, nil 214 } 215 return nil, fmt.Errorf("portal not found") 216 } 217 218 // GetGatekeeperByName returns an instance of authz.Gatekeeper based on its name. 219 func (srv *Server) GetGatekeeperByName(s string) (*authz.Gatekeeper, error) { 220 if gatekeeper, exists := srv.nameRefs.gatekeepers[s]; exists { 221 return gatekeeper, nil 222 } 223 return nil, fmt.Errorf("gatekeeper not found") 224 }