github.com/greenpau/go-authcrunch@v1.1.4/pkg/ids/local/authenticator.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  	"os"
    19  	"sync"
    20  
    21  	"github.com/google/uuid"
    22  	"github.com/greenpau/go-authcrunch/pkg/identity"
    23  	"github.com/greenpau/go-authcrunch/pkg/requests"
    24  	"go.uber.org/zap"
    25  )
    26  
    27  const (
    28  	defaultAdminRoleName = "authp/admin"
    29  )
    30  
    31  // Authenticator represents database connector.
    32  type Authenticator struct {
    33  	db     *identity.Database
    34  	mux    sync.Mutex
    35  	path   string
    36  	logger *zap.Logger
    37  }
    38  
    39  // NewAuthenticator returns an instance of Authenticator.
    40  func NewAuthenticator() *Authenticator {
    41  	return &Authenticator{}
    42  }
    43  
    44  // Configure check database connectivity and required tables.
    45  func (sa *Authenticator) Configure(fp string, users []*User) error {
    46  	sa.mux.Lock()
    47  	defer sa.mux.Unlock()
    48  	sa.logger.Info(
    49  		"identity store authenticator configuration",
    50  		zap.String("kind", storeKind),
    51  		zap.String("db_path", fp),
    52  	)
    53  	sa.path = fp
    54  
    55  	db, err := identity.NewDatabase(fp)
    56  	if err != nil {
    57  		return err
    58  	}
    59  	sa.db = db
    60  
    61  	if len(users) > 0 {
    62  		for _, user := range users {
    63  			// Check whether user exists.
    64  			userFound, err := sa.db.UserExists(user.Username, user.EmailAddress)
    65  			if err != nil {
    66  				return err
    67  			}
    68  			if !userFound {
    69  				sa.logger.Debug(
    70  					"creating statically-defined identity store user",
    71  					zap.String("user", user.Username),
    72  					zap.String("email", user.EmailAddress),
    73  				)
    74  				// Create user.
    75  				req := &requests.Request{
    76  					User: requests.User{
    77  						Username: user.Username,
    78  						Password: user.Password,
    79  						Email:    user.EmailAddress,
    80  						Roles:    user.Roles,
    81  						FullName: user.Name,
    82  					},
    83  				}
    84  				if err := sa.db.AddUser(req); err != nil {
    85  					return err
    86  				}
    87  			} else {
    88  				if user.PasswordOverwriteEnabled {
    89  					sa.logger.Debug(
    90  						"updating password for statically-defined identity store user",
    91  						zap.String("user", user.Username),
    92  						zap.String("email", user.EmailAddress),
    93  					)
    94  					// Update password (if overwrite is enabled).
    95  					req := &requests.Request{
    96  						User: requests.User{
    97  							Username: user.Username,
    98  							Password: user.Password,
    99  							Email:    user.EmailAddress,
   100  						},
   101  					}
   102  					if err := sa.db.UpdateUserPassword(req); err != nil {
   103  						return err
   104  					}
   105  				}
   106  			}
   107  		}
   108  	}
   109  
   110  	if sa.db.GetAdminUserCount() < 1 {
   111  		req := &requests.Request{
   112  			User: requests.User{
   113  				Username: os.Getenv("AUTHP_ADMIN_USER"),
   114  				Password: os.Getenv("AUTHP_ADMIN_SECRET"),
   115  				Email:    os.Getenv("AUTHP_ADMIN_EMAIL"),
   116  				Roles:    []string{defaultAdminRoleName},
   117  			},
   118  		}
   119  
   120  		if req.User.Username == "" {
   121  			req.User.Username = "webadmin"
   122  		}
   123  
   124  		if req.User.Password == "" {
   125  			req.User.Password = uuid.New().String()
   126  		}
   127  
   128  		if req.User.Email == "" {
   129  			req.User.Email = "webadmin@localdomain.local"
   130  		}
   131  
   132  		if err := sa.db.AddUser(req); err != nil {
   133  			return err
   134  		}
   135  		sa.logger.Info("created default admin user for the database",
   136  			zap.String("username", req.User.Username),
   137  			zap.String("email", req.User.Email),
   138  			zap.Any("roles", req.User.Roles),
   139  		)
   140  	}
   141  	return nil
   142  }
   143  
   144  // AuthenticateUser checks the database for the presence of a username/email
   145  // and password and returns user claims.
   146  func (sa *Authenticator) AuthenticateUser(r *requests.Request) error {
   147  	sa.mux.Lock()
   148  	defer sa.mux.Unlock()
   149  	return sa.db.AuthenticateUser(r)
   150  }
   151  
   152  // AddUser adds a user to database.
   153  func (sa *Authenticator) AddUser(r *requests.Request) error {
   154  	sa.mux.Lock()
   155  	defer sa.mux.Unlock()
   156  	return sa.db.AddUser(r)
   157  }
   158  
   159  // GetUsers retrieves users from database.
   160  func (sa *Authenticator) GetUsers(r *requests.Request) error {
   161  	sa.mux.Lock()
   162  	defer sa.mux.Unlock()
   163  	return sa.db.GetUsers(r)
   164  }
   165  
   166  // GetUser retrieves a specific user from database.
   167  func (sa *Authenticator) GetUser(r *requests.Request) error {
   168  	sa.mux.Lock()
   169  	defer sa.mux.Unlock()
   170  	return sa.db.GetUser(r)
   171  }
   172  
   173  // DeleteUser delete a specific user from database.
   174  func (sa *Authenticator) DeleteUser(r *requests.Request) error {
   175  	sa.mux.Lock()
   176  	defer sa.mux.Unlock()
   177  	return sa.db.DeleteUser(r)
   178  }
   179  
   180  // ChangePassword changes password for a user.
   181  func (sa *Authenticator) ChangePassword(r *requests.Request) error {
   182  	sa.mux.Lock()
   183  	defer sa.mux.Unlock()
   184  	return sa.db.ChangeUserPassword(r)
   185  }
   186  
   187  // AddPublicKey adds public key, e.g. GPG or SSH, for a user.
   188  func (sa *Authenticator) AddPublicKey(r *requests.Request) error {
   189  	sa.mux.Lock()
   190  	defer sa.mux.Unlock()
   191  	return sa.db.AddPublicKey(r)
   192  }
   193  
   194  // DeletePublicKey removes a public key, e.g. GPG or SSH, associated with the user.
   195  func (sa *Authenticator) DeletePublicKey(r *requests.Request) error {
   196  	sa.mux.Lock()
   197  	defer sa.mux.Unlock()
   198  	return sa.db.DeletePublicKey(r)
   199  }
   200  
   201  // GetPublicKeys returns a list of public keys associated with a user.
   202  func (sa *Authenticator) GetPublicKeys(r *requests.Request) error {
   203  	sa.mux.Lock()
   204  	defer sa.mux.Unlock()
   205  	return sa.db.GetPublicKeys(r)
   206  }
   207  
   208  // GetPublicKey returns a public keys associated with a user.
   209  func (sa *Authenticator) GetPublicKey(r *requests.Request) error {
   210  	sa.mux.Lock()
   211  	defer sa.mux.Unlock()
   212  	return sa.db.GetPublicKey(r)
   213  }
   214  
   215  // AddAPIKey adds API key for a user.
   216  func (sa *Authenticator) AddAPIKey(r *requests.Request) error {
   217  	sa.mux.Lock()
   218  	defer sa.mux.Unlock()
   219  	return sa.db.AddAPIKey(r)
   220  }
   221  
   222  // DeleteAPIKey removes API key associated with the user.
   223  func (sa *Authenticator) DeleteAPIKey(r *requests.Request) error {
   224  	sa.mux.Lock()
   225  	defer sa.mux.Unlock()
   226  	return sa.db.DeleteAPIKey(r)
   227  }
   228  
   229  // GetAPIKeys returns a list of  API keys associated with a user.
   230  func (sa *Authenticator) GetAPIKeys(r *requests.Request) error {
   231  	sa.mux.Lock()
   232  	defer sa.mux.Unlock()
   233  	return sa.db.GetAPIKeys(r)
   234  }
   235  
   236  // GetAPIKey returns API key associated with a user.
   237  func (sa *Authenticator) GetAPIKey(r *requests.Request) error {
   238  	sa.mux.Lock()
   239  	defer sa.mux.Unlock()
   240  	return sa.db.GetAPIKey(r)
   241  }
   242  
   243  // AddMfaToken adds MFA token to a user.
   244  func (sa *Authenticator) AddMfaToken(r *requests.Request) error {
   245  	sa.mux.Lock()
   246  	defer sa.mux.Unlock()
   247  	return sa.db.AddMfaToken(r)
   248  }
   249  
   250  // DeleteMfaToken removes MFA token associated with the user.
   251  func (sa *Authenticator) DeleteMfaToken(r *requests.Request) error {
   252  	sa.mux.Lock()
   253  	defer sa.mux.Unlock()
   254  	return sa.db.DeleteMfaToken(r)
   255  }
   256  
   257  // GetMfaTokens returns a list of MFA token associated with a user.
   258  func (sa *Authenticator) GetMfaTokens(r *requests.Request) error {
   259  	sa.mux.Lock()
   260  	defer sa.mux.Unlock()
   261  	return sa.db.GetMfaTokens(r)
   262  }
   263  
   264  // GetMfaToken returns a single MFA token associated with a user.
   265  func (sa *Authenticator) GetMfaToken(r *requests.Request) error {
   266  	sa.mux.Lock()
   267  	defer sa.mux.Unlock()
   268  	return sa.db.GetMfaToken(r)
   269  }
   270  
   271  // IdentifyUser returns user challenges.
   272  func (sa *Authenticator) IdentifyUser(r *requests.Request) error {
   273  	sa.mux.Lock()
   274  	defer sa.mux.Unlock()
   275  	return sa.db.IdentifyUser(r)
   276  }
   277  
   278  // LookupAPIKey performs user lookup based on an API key.
   279  func (sa *Authenticator) LookupAPIKey(r *requests.Request) error {
   280  	sa.mux.Lock()
   281  	defer sa.mux.Unlock()
   282  	return sa.db.LookupAPIKey(r)
   283  }