influxdb/v1/authorization/service_password.go

107 lines
2.8 KiB
Go

package authorization
import (
"context"
"github.com/influxdata/influxdb/v2/kit/platform"
"github.com/influxdata/influxdb/v2/kit/platform/errors"
"github.com/influxdata/influxdb/v2/kv"
"github.com/influxdata/influxdb/v2/tenant"
"golang.org/x/crypto/bcrypt"
)
var EIncorrectPassword = tenant.EIncorrectPassword
// SetPasswordHash updates the password hash for id. If passHash is not a valid bcrypt hash,
// SetPasswordHash returns an error.
//
// This API is intended for upgrading 1.x users.
func (s *Service) SetPasswordHash(ctx context.Context, authID platform.ID, passHash string) error {
// verify passHash is a valid bcrypt hash
_, err := bcrypt.Cost([]byte(passHash))
if err != nil {
return &errors.Error{
Code: errors.EInvalid,
Msg: "invalid bcrypt hash",
Err: err,
}
}
// set password
return s.store.Update(ctx, func(tx kv.Tx) error {
_, err := s.store.GetAuthorizationByID(ctx, tx, authID)
if err != nil {
return ErrAuthNotFound
}
return s.store.SetPassword(ctx, tx, authID, passHash)
})
}
// SetPassword overrides the password of a known user.
func (s *Service) SetPassword(ctx context.Context, authID platform.ID, password string) error {
if len(password) < tenant.MinPasswordLen {
return tenant.EShortPassword
}
passHash, err := encryptPassword(password)
if err != nil {
return err
}
// set password
return s.store.Update(ctx, func(tx kv.Tx) error {
_, err := s.store.GetAuthorizationByID(ctx, tx, authID)
if err != nil {
return ErrAuthNotFound
}
return s.store.SetPassword(ctx, tx, authID, passHash)
})
}
// ComparePassword checks if the password matches the password recorded.
// Passwords that do not match return errors.
func (s *Service) ComparePassword(ctx context.Context, authID platform.ID, password string) error {
// get password
var hash []byte
err := s.store.View(ctx, func(tx kv.Tx) error {
_, err := s.store.GetAuthorizationByID(ctx, tx, authID)
if err != nil {
return ErrAuthNotFound
}
h, err := s.store.GetPassword(ctx, tx, authID)
if err != nil {
if err == kv.ErrKeyNotFound {
return EIncorrectPassword
}
return err
}
hash = []byte(h)
return nil
})
if err != nil {
return err
}
// compare password
if err := bcrypt.CompareHashAndPassword(hash, []byte(password)); err != nil {
return EIncorrectPassword
}
return nil
}
// CompareAndSetPassword checks the password and if they match
// updates to the new password.
func (s *Service) CompareAndSetPassword(ctx context.Context, authID platform.ID, old, new string) error {
err := s.ComparePassword(ctx, authID, old)
if err != nil {
return err
}
return s.SetPassword(ctx, authID, new)
}
func encryptPassword(password string) (string, error) {
passHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(passHash), nil
}