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