github.com/greenpau/go-authcrunch@v1.0.50/pkg/ids/local/store.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 local 16 17 import ( 18 "encoding/json" 19 "github.com/greenpau/go-authcrunch/pkg/authn/enums/operator" 20 "github.com/greenpau/go-authcrunch/pkg/authn/icons" 21 "github.com/greenpau/go-authcrunch/pkg/errors" 22 "github.com/greenpau/go-authcrunch/pkg/requests" 23 "go.uber.org/zap" 24 ) 25 26 const ( 27 storeKind = "local" 28 ) 29 30 // Config holds the configuration for the identity store. 31 type Config struct { 32 Name string `json:"name,omitempty" xml:"name,omitempty" yaml:"name,omitempty"` 33 Realm string `json:"realm,omitempty" xml:"realm,omitempty" yaml:"realm,omitempty"` 34 Path string `json:"path,omitempty" xml:"path,omitempty" yaml:"path,omitempty"` 35 Users []*User `json:"users,omitempty" xml:"users,omitempty" yaml:"users,omitempty"` 36 37 // LoginIcon is the UI login icon attributes. 38 LoginIcon *icons.LoginIcon `json:"login_icon,omitempty" xml:"login_icon,omitempty" yaml:"login_icon,omitempty"` 39 40 // RegistrationEnabled controls whether visitors can registers. 41 RegistrationEnabled bool `json:"registration_enabled,omitempty" xml:"registration_enabled,omitempty" yaml:"registration_enabled,omitempty"` 42 // UsernameRecoveryEnabled controls whether a user could recover username by providing an email address. 43 UsernameRecoveryEnabled bool `json:"username_recovery_enabled,omitempty" xml:"username_recovery_enabled,omitempty" yaml:"username_recovery_enabled,omitempty"` 44 // PasswordRecoveryEnabled controls whether a user could recover password by providing an email address. 45 PasswordRecoveryEnabled bool `json:"password_recovery_enabled,omitempty" xml:"password_recovery_enabled,omitempty" yaml:"password_recovery_enabled,omitempty"` 46 // ContactSupportEnabled controls whether contact support link is available. 47 ContactSupportEnabled bool `json:"contact_support_enabled,omitempty" xml:"contact_support_enabled,omitempty" yaml:"contact_support_enabled,omitempty"` 48 49 // SupportLink is the link to the support portal. 50 SupportLink string `json:"support_link,omitempty" xml:"support_link,omitempty" yaml:"support_link,omitempty"` 51 // SupportEmail is the email address to reach support. 52 SupportEmail string `json:"support_email,omitempty" xml:"support_email,omitempty" yaml:"support_email,omitempty"` 53 } 54 55 // IdentityStore represents authentication provider with local identity store. 56 type IdentityStore struct { 57 config *Config `json:"-"` 58 authenticator *Authenticator `json:"-"` 59 logger *zap.Logger 60 configured bool 61 } 62 63 // NewIdentityStore return an instance of AuthDB-based identity store. 64 func NewIdentityStore(cfg *Config, logger *zap.Logger) (*IdentityStore, error) { 65 if logger == nil { 66 return nil, errors.ErrIdentityStoreConfigureLoggerNotFound 67 } 68 69 b := &IdentityStore{ 70 config: cfg, 71 logger: logger, 72 } 73 74 // Configure UI login icon. 75 if b.config.LoginIcon == nil { 76 b.config.LoginIcon = icons.NewLoginIcon(storeKind) 77 } else { 78 b.config.LoginIcon.Configure(storeKind) 79 } 80 81 if err := b.config.Validate(); err != nil { 82 return nil, err 83 } 84 85 return b, nil 86 } 87 88 // GetRealm return authentication realm. 89 func (b *IdentityStore) GetRealm() string { 90 return b.config.Realm 91 } 92 93 // GetName return the name associated with this identity store. 94 func (b *IdentityStore) GetName() string { 95 return b.config.Name 96 } 97 98 // GetKind returns the authentication method associated with this identity store. 99 func (b *IdentityStore) GetKind() string { 100 return storeKind 101 } 102 103 // Configured returns true if the identity store was configured. 104 func (b *IdentityStore) Configured() bool { 105 return b.configured 106 } 107 108 // Request performs the requested identity store operation. 109 func (b *IdentityStore) Request(op operator.Type, r *requests.Request) error { 110 switch op { 111 case operator.Authenticate: 112 return b.Authenticate(r) 113 case operator.IdentifyUser: 114 return b.authenticator.IdentifyUser(r) 115 case operator.ChangePassword: 116 return b.authenticator.ChangePassword(r) 117 case operator.AddKeySSH: 118 return b.authenticator.AddPublicKey(r) 119 case operator.AddKeyGPG: 120 return b.authenticator.AddPublicKey(r) 121 case operator.DeletePublicKey: 122 return b.authenticator.DeletePublicKey(r) 123 case operator.AddMfaToken: 124 // b.logger.Debug("detected supported identity store operation", zap.Any("op", op), zap.Any("params", r)) 125 return b.authenticator.AddMfaToken(r) 126 case operator.DeleteMfaToken: 127 return b.authenticator.DeleteMfaToken(r) 128 case operator.AddAPIKey: 129 return b.authenticator.AddAPIKey(r) 130 case operator.DeleteAPIKey: 131 return b.authenticator.DeleteAPIKey(r) 132 case operator.GetPublicKeys: 133 return b.authenticator.GetPublicKeys(r) 134 case operator.GetAPIKeys: 135 return b.authenticator.GetAPIKeys(r) 136 case operator.GetMfaTokens: 137 return b.authenticator.GetMfaTokens(r) 138 case operator.AddUser: 139 return b.authenticator.AddUser(r) 140 case operator.GetUsers: 141 return b.authenticator.GetUsers(r) 142 case operator.GetUser: 143 return b.authenticator.GetUser(r) 144 case operator.DeleteUser: 145 return b.authenticator.DeleteUser(r) 146 case operator.LookupAPIKey: 147 return b.authenticator.LookupAPIKey(r) 148 } 149 150 b.logger.Error( 151 "detected unsupported identity store operation", 152 zap.Any("op", op), 153 zap.Any("params", r), 154 ) 155 return errors.ErrOperatorNotSupported.WithArgs(op) 156 } 157 158 // Configure configures IdentityStore. 159 func (b *IdentityStore) Configure() error { 160 if b.authenticator == nil { 161 b.authenticator = NewAuthenticator() 162 } 163 b.authenticator.logger = b.logger 164 165 if err := b.authenticator.Configure(b.config.Path, b.config.Users); err != nil { 166 return err 167 } 168 169 b.logger.Info( 170 "successfully configured identity store", 171 zap.String("name", b.config.Name), 172 zap.String("kind", storeKind), 173 zap.String("db_path", b.config.Path), 174 zap.Any("login_icon", b.config.LoginIcon), 175 ) 176 177 b.configured = true 178 return nil 179 } 180 181 // GetConfig returns IdentityStore configuration. 182 func (b *IdentityStore) GetConfig() map[string]interface{} { 183 var m map[string]interface{} 184 j, _ := json.Marshal(b.config) 185 json.Unmarshal(j, &m) 186 return m 187 } 188 189 // Authenticate performs authentication. 190 func (b *IdentityStore) Authenticate(r *requests.Request) error { 191 if err := b.authenticator.AuthenticateUser(r); err != nil { 192 return errors.ErrIdentityStoreLocalAuthFailed.WithArgs(err) 193 } 194 return nil 195 } 196 197 // Validate validates identity store configuration. 198 func (cfg *Config) Validate() error { 199 if cfg.Name == "" { 200 return errors.ErrIdentityStoreConfigureNameEmpty 201 } 202 if cfg.Realm == "" { 203 return errors.ErrIdentityStoreConfigureRealmEmpty 204 } 205 if cfg.Path == "" { 206 return errors.ErrIdentityStoreLocalConfigurePathEmpty 207 } 208 return nil 209 } 210 211 // GetLoginIcon returns the instance of the icon associated with the provider. 212 func (b *IdentityStore) GetLoginIcon() *icons.LoginIcon { 213 // Add support and credentials recovery to the UI login icon. 214 b.config.LoginIcon.RegistrationEnabled = b.config.RegistrationEnabled 215 b.config.LoginIcon.UsernameRecoveryEnabled = b.config.UsernameRecoveryEnabled 216 b.config.LoginIcon.PasswordRecoveryEnabled = b.config.PasswordRecoveryEnabled 217 b.config.LoginIcon.ContactSupportEnabled = b.config.ContactSupportEnabled 218 b.config.LoginIcon.SupportLink = b.config.SupportLink 219 b.config.LoginIcon.SupportEmail = b.config.SupportEmail 220 return b.config.LoginIcon 221 }