Migrat pkg/password to using pkglib package
This commit is contained in:
parent
010fd536ea
commit
aa3580c248
11 changed files with 56 additions and 158 deletions
|
|
@ -1,8 +1,13 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import "github.com/FAU-CDI/wisski-distillery/pkg/password"
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/passwordx"
|
||||||
|
"github.com/tkw1536/pkglib/password"
|
||||||
|
)
|
||||||
|
|
||||||
// NewPassword returns a new password using the password settings from this configuration
|
// NewPassword returns a new password using the password settings from this configuration
|
||||||
func (cfg Config) NewPassword() (string, error) {
|
func (cfg Config) NewPassword() (string, error) {
|
||||||
return password.Password(cfg.PasswordLength)
|
return password.Generate(rand.Reader, cfg.PasswordLength, passwordx.Charset)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/bootstrap"
|
"github.com/FAU-CDI/wisski-distillery/internal/bootstrap"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/passwordx"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/password"
|
|
||||||
"github.com/tkw1536/pkglib/hostname"
|
"github.com/tkw1536/pkglib/hostname"
|
||||||
|
"github.com/tkw1536/pkglib/password"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Template is a template for the configuration file
|
// Template is a template for the configuration file
|
||||||
|
|
@ -47,7 +49,7 @@ func (tpl *Template) SetDefaults(env environment.Environment) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if tpl.TriplestoreAdminPassword == "" {
|
if tpl.TriplestoreAdminPassword == "" {
|
||||||
tpl.TriplestoreAdminPassword, err = password.Password(64)
|
tpl.TriplestoreAdminPassword, err = password.Generate(rand.Reader, 64, passwordx.Charset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -58,14 +60,14 @@ func (tpl *Template) SetDefaults(env environment.Environment) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if tpl.MysqlAdminPassword == "" {
|
if tpl.MysqlAdminPassword == "" {
|
||||||
tpl.MysqlAdminPassword, err = password.Password(64)
|
tpl.MysqlAdminPassword, err = password.Generate(rand.Reader, 64, passwordx.Charset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tpl.DockerNetworkName == "" {
|
if tpl.DockerNetworkName == "" {
|
||||||
tpl.DockerNetworkName, err = password.Password(10)
|
tpl.DockerNetworkName, err = password.Generate(rand.Reader, 10, passwordx.Charset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +75,7 @@ func (tpl *Template) SetDefaults(env environment.Environment) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if tpl.SessionSecret == "" {
|
if tpl.SessionSecret == "" {
|
||||||
tpl.SessionSecret, err = password.Password(100)
|
tpl.SessionSecret, err = password.Generate(rand.Reader, 100, passwordx.Charset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,11 @@ import (
|
||||||
|
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/password"
|
"github.com/FAU-CDI/wisski-distillery/internal/passwordx"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/pquerna/otp"
|
"github.com/pquerna/otp"
|
||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
|
"github.com/tkw1536/pkglib/password"
|
||||||
"github.com/tkw1536/pkglib/pools"
|
"github.com/tkw1536/pkglib/pools"
|
||||||
"github.com/tkw1536/pkglib/reflectx"
|
"github.com/tkw1536/pkglib/reflectx"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
|
|
@ -263,7 +264,7 @@ func (auth *Auth) CheckPasswordPolicy(candidate string, username string) error {
|
||||||
return ErrPolicyTooShort
|
return ErrPolicyTooShort
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := password.CheckCommonPassword(func(common string) (bool, error) { return common == candidate, nil }); err != nil {
|
if err := password.CheckCommonPassword(func(common string) (bool, error) { return common == candidate, nil }, passwordx.Sources...); err != nil {
|
||||||
return ErrPolicyKnown
|
return ErrPolicyKnown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
package exporter
|
package exporter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||||
|
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter/logger"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter/logger"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/sql"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/sql"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/passwordx"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
"github.com/FAU-CDI/wisski-distillery/pkg/environment"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
"github.com/FAU-CDI/wisski-distillery/pkg/fsx"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/password"
|
"github.com/tkw1536/pkglib/password"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Exporter manages snapshots and backups
|
// Exporter manages snapshots and backups
|
||||||
|
|
@ -59,7 +60,7 @@ func (dis *Exporter) NewArchivePath(prefix string) (path string) {
|
||||||
// newSnapshot name returns a new basename for a snapshot with the provided prefix.
|
// newSnapshot name returns a new basename for a snapshot with the provided prefix.
|
||||||
// The name is guaranteed to be unique within this process.
|
// The name is guaranteed to be unique within this process.
|
||||||
func (*Exporter) newSnapshotName(prefix string) string {
|
func (*Exporter) newSnapshotName(prefix string) string {
|
||||||
suffix, _ := password.Password(10) // silently ignore any errors!
|
suffix, _ := password.Generate(rand.Reader, 10, passwordx.Snapshot) // silently ignore any errors!
|
||||||
if prefix == "" {
|
if prefix == "" {
|
||||||
prefix = "backup"
|
prefix = "backup"
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
9
internal/passwordx/charset.go
Normal file
9
internal/passwordx/charset.go
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
package passwordx
|
||||||
|
|
||||||
|
import "github.com/tkw1536/pkglib/password"
|
||||||
|
|
||||||
|
// Charset is a Charset safe for usage within the distillery
|
||||||
|
const Charset = password.DefaultCharSet
|
||||||
|
|
||||||
|
// Snapshot is a charset to be used to generate snapshot ids
|
||||||
|
const Snapshot = password.DefaultCharSet
|
||||||
23
internal/passwordx/common.go
Normal file
23
internal/passwordx/common.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package passwordx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
|
||||||
|
"github.com/tkw1536/pkglib/password"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed common
|
||||||
|
var commonEmbed embed.FS
|
||||||
|
|
||||||
|
var Sources []password.PasswordSource
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
var err error
|
||||||
|
Sources, err = password.NewSources(commonEmbed, "**/*.txt")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if len(Sources) == 0 {
|
||||||
|
panic("no sources")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,8 +6,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/passwordx"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/phpx"
|
"github.com/FAU-CDI/wisski-distillery/internal/phpx"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/password"
|
"github.com/tkw1536/pkglib/password"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errGetValidator = errors.New("GetPasswordValidator: Unknown Error")
|
var errGetValidator = errors.New("GetPasswordValidator: Unknown Error")
|
||||||
|
|
@ -64,7 +65,7 @@ func (pv PasswordValidator) CheckDictionary(ctx context.Context, writer io.Write
|
||||||
}
|
}
|
||||||
return errPasswordUsername
|
return errPasswordUsername
|
||||||
}
|
}
|
||||||
for candidate := range password.CommonPasswords() {
|
for candidate := range password.Passwords(passwordx.Sources...) {
|
||||||
if ctx.Err() != nil {
|
if ctx.Err() != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
package password
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"embed"
|
|
||||||
"fmt"
|
|
||||||
"io/fs"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CommonPasswordError
|
|
||||||
type CommonPasswordError struct {
|
|
||||||
CommonPassword
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cpe CommonPasswordError) Error() string {
|
|
||||||
return fmt.Sprintf("%q from %q", cpe.Password, cpe.Source)
|
|
||||||
}
|
|
||||||
|
|
||||||
type CommonPassword struct {
|
|
||||||
Password string
|
|
||||||
Source string
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:embed common
|
|
||||||
var commonEmbed embed.FS
|
|
||||||
|
|
||||||
// CommonPasswords returns a channel that contains all passwords.
|
|
||||||
// The caller must drain the channel.
|
|
||||||
func CommonPasswords() <-chan CommonPassword {
|
|
||||||
pChan := make(chan CommonPassword, 10)
|
|
||||||
go func() {
|
|
||||||
defer close(pChan)
|
|
||||||
|
|
||||||
fs.WalkDir(commonEmbed, ".", func(path string, d fs.DirEntry, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the full path
|
|
||||||
if d.IsDir() || !strings.HasSuffix(path, ".txt") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// open it
|
|
||||||
file, err := commonEmbed.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
// scan it line by line
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := strings.TrimSpace(scanner.Text())
|
|
||||||
if line == "" || strings.HasPrefix(line, "//") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
pChan <- CommonPassword{
|
|
||||||
Password: line,
|
|
||||||
Source: path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return scanner.Err()
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
return pChan
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckCommonPassword checks if a password is a common password.
|
|
||||||
//
|
|
||||||
// check is called with each candidate password to perform the check.
|
|
||||||
// check should return a boolean indicating if the password in question corresponds to the candidate.
|
|
||||||
//
|
|
||||||
// CheckCommonPassword returns one of three error values.
|
|
||||||
//
|
|
||||||
// - a CommonPasswordError (when a password matches a common password)
|
|
||||||
// - an error returned by check (assuming some check went wrong)
|
|
||||||
// - or nil (when a password is not a common password
|
|
||||||
func CheckCommonPassword(check func(candidate string) (bool, error)) error {
|
|
||||||
for commmon := range CommonPasswords() {
|
|
||||||
ok, err := check(commmon.Password)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// password validation passed
|
|
||||||
if ok {
|
|
||||||
return CommonPasswordError{
|
|
||||||
CommonPassword: commmon,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
// Package password allows generating random passwords
|
|
||||||
package password
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/rand"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/tkw1536/pkglib/pools"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NOTE(twiesing): A bunch of scripts cannot properly handle the extra characters in the password.
|
|
||||||
// For now it is disabled, but it should be re-enabled later.
|
|
||||||
const PasswordCharSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" // + "!@#$%&*"
|
|
||||||
var passwordCharCount = big.NewInt(int64(len(PasswordCharSet)))
|
|
||||||
|
|
||||||
// Password returns a randomly generated string with the provided length.
|
|
||||||
// It consists of alphanumeric characters only.
|
|
||||||
//
|
|
||||||
// When an error occurs, it is guaranteed to return "", err.
|
|
||||||
// [rand.Reader] is used as the source of randomness.
|
|
||||||
func Password(length int) (string, error) {
|
|
||||||
if length < 0 {
|
|
||||||
panic("length < 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a buffer to write the string to!
|
|
||||||
password := pools.GetBuilder()
|
|
||||||
defer pools.ReleaseBuilder(password)
|
|
||||||
password.Grow(length)
|
|
||||||
|
|
||||||
for i := 0; i < length; i++ {
|
|
||||||
|
|
||||||
// grab a random bIndex!
|
|
||||||
bIndex, err := rand.Int(rand.Reader, passwordCharCount)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// and use that index!
|
|
||||||
index := int(bIndex.Int64())
|
|
||||||
if err := password.WriteByte(PasswordCharSet[index]); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the password!
|
|
||||||
return password.String(), nil
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue