feat(commands): random character generator (#4213)

This improves all random character generator command usages to be nearly identical and reuse a large block of code. It also improves several functions to give more options when randomly generating outputs.
pull/4219/head
James Elliott 2022-10-21 07:41:46 +11:00 committed by GitHub
parent 3f8958d1b1
commit 3113ec2b80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 186 additions and 136 deletions

View File

@ -2,7 +2,7 @@
title: "Specific Information" title: "Specific Information"
description: "Specific information regarding integrating the Authelia OpenID Connect Provider with an OpenID Connect relying party" description: "Specific information regarding integrating the Authelia OpenID Connect Provider with an OpenID Connect relying party"
lead: "Specific information regarding integrating the Authelia OpenID Connect Provider with an OpenID Connect relying party." lead: "Specific information regarding integrating the Authelia OpenID Connect Provider with an OpenID Connect relying party."
date: 2022-06-15T17:51:47+10:00 date: 2022-10-20T15:27:09+11:00
draft: false draft: false
images: [] images: []
menu: menu:

View File

@ -37,10 +37,14 @@ authelia crypto hash generate --help
### Options ### Options
``` ```
-c, --config strings configuration files to load (default [configuration.yml]) -c, --config strings configuration files to load (default [configuration.yml])
-h, --help help for generate -h, --help help for generate
--no-confirm skip the password confirmation prompt --no-confirm skip the password confirmation prompt
--password string manually supply the password rather than using the terminal prompt --password string manually supply the password rather than using the terminal prompt
--random uses a randomly generated password
--random.characters string sets the explicit characters for the random string
--random.charset string sets the charset for the random password, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex' (default "alphanumeric")
--random.length int when using a randomly generated password it configures the length (default 72)
``` ```
### SEE ALSO ### SEE ALSO

View File

@ -35,19 +35,26 @@ authelia crypto hash generate argon2 --help
### Options ### Options
``` ```
-c, --config strings configuration files to load (default [configuration.yml]) -h, --help help for argon2
-h, --help help for argon2 -i, --iterations int number of iterations (default 3)
-i, --iterations int number of iterations (default 3) -k, --key-size int key size in bytes (default 32)
-k, --key-size int key size in bytes (default 32) -m, --memory int memory in kibibytes (default 65536)
-m, --memory int memory in kibibytes (default 65536) -p, --parallelism int parallelism or threads (default 4)
--no-confirm skip the password confirmation prompt --profile string profile to use, options are low-memory and recommended
-p, --parallelism int parallelism or threads (default 4) -s, --salt-size int salt size in bytes (default 16)
--password string manually supply the password rather than using the terminal prompt -v, --variant string variant, options are 'argon2id', 'argon2i', and 'argon2d' (default "argon2id")
--profile string profile to use, options are low-memory and recommended ```
--random uses a randomly generated password
--random.length int when using a randomly generated password it configures the length (default 72) ### Options inherited from parent commands
-s, --salt-size int salt size in bytes (default 16)
-v, --variant string variant, options are 'argon2id', 'argon2i', and 'argon2d' (default "argon2id") ```
-c, --config strings configuration files to load (default [configuration.yml])
--no-confirm skip the password confirmation prompt
--password string manually supply the password rather than using the terminal prompt
--random uses a randomly generated password
--random.characters string sets the explicit characters for the random string
--random.charset string sets the charset for the random password, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex' (default "alphanumeric")
--random.length int when using a randomly generated password it configures the length (default 72)
``` ```
### SEE ALSO ### SEE ALSO

View File

@ -35,14 +35,21 @@ authelia crypto hash generate bcrypt --help
### Options ### Options
``` ```
-c, --config strings configuration files to load (default [configuration.yml]) -i, --cost int hashing cost (default 12)
-i, --cost int hashing cost (default 12) -h, --help help for bcrypt
-h, --help help for bcrypt -v, --variant string variant, options are 'standard' and 'sha256' (default "standard")
--no-confirm skip the password confirmation prompt ```
--password string manually supply the password rather than using the terminal prompt
--random uses a randomly generated password ### Options inherited from parent commands
--random.length int when using a randomly generated password it configures the length (default 72)
-v, --variant string variant, options are 'standard' and 'sha256' (default "standard") ```
-c, --config strings configuration files to load (default [configuration.yml])
--no-confirm skip the password confirmation prompt
--password string manually supply the password rather than using the terminal prompt
--random uses a randomly generated password
--random.characters string sets the explicit characters for the random string
--random.charset string sets the charset for the random password, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex' (default "alphanumeric")
--random.length int when using a randomly generated password it configures the length (default 72)
``` ```
### SEE ALSO ### SEE ALSO

View File

@ -35,15 +35,22 @@ authelia crypto hash generate pbkdf2 --help
### Options ### Options
``` ```
-c, --config strings configuration files to load (default [configuration.yml]) -h, --help help for pbkdf2
-h, --help help for pbkdf2 -i, --iterations int number of iterations (default 310000)
-i, --iterations int number of iterations (default 310000) -s, --salt-size int salt size in bytes (default 16)
--no-confirm skip the password confirmation prompt -v, --variant string variant, options are 'sha1', 'sha224', 'sha256', 'sha384', and 'sha512' (default "sha512")
--password string manually supply the password rather than using the terminal prompt ```
--random uses a randomly generated password
--random.length int when using a randomly generated password it configures the length (default 72) ### Options inherited from parent commands
-s, --salt-size int salt size in bytes (default 16)
-v, --variant string variant, options are 'sha1', 'sha224', 'sha256', 'sha384', and 'sha512' (default "sha512") ```
-c, --config strings configuration files to load (default [configuration.yml])
--no-confirm skip the password confirmation prompt
--password string manually supply the password rather than using the terminal prompt
--random uses a randomly generated password
--random.characters string sets the explicit characters for the random string
--random.charset string sets the charset for the random password, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex' (default "alphanumeric")
--random.length int when using a randomly generated password it configures the length (default 72)
``` ```
### SEE ALSO ### SEE ALSO

View File

@ -35,17 +35,24 @@ authelia crypto hash generate scrypt --help
### Options ### Options
``` ```
-r, --block-size int block size (default 8) -r, --block-size int block size (default 8)
-c, --config strings configuration files to load (default [configuration.yml]) -h, --help help for scrypt
-h, --help help for scrypt -i, --iterations int number of iterations (default 16)
-i, --iterations int number of iterations (default 16) -k, --key-size int key size in bytes (default 32)
-k, --key-size int key size in bytes (default 32) -p, --parallelism int parallelism or threads (default 1)
--no-confirm skip the password confirmation prompt -s, --salt-size int salt size in bytes (default 16)
-p, --parallelism int parallelism or threads (default 1) ```
--password string manually supply the password rather than using the terminal prompt
--random uses a randomly generated password ### Options inherited from parent commands
--random.length int when using a randomly generated password it configures the length (default 72)
-s, --salt-size int salt size in bytes (default 16) ```
-c, --config strings configuration files to load (default [configuration.yml])
--no-confirm skip the password confirmation prompt
--password string manually supply the password rather than using the terminal prompt
--random uses a randomly generated password
--random.characters string sets the explicit characters for the random string
--random.charset string sets the charset for the random password, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex' (default "alphanumeric")
--random.length int when using a randomly generated password it configures the length (default 72)
``` ```
### SEE ALSO ### SEE ALSO

View File

@ -35,15 +35,22 @@ authelia crypto hash generate sha2crypt --help
### Options ### Options
``` ```
-c, --config strings configuration files to load (default [configuration.yml]) -h, --help help for sha2crypt
-h, --help help for sha2crypt -i, --iterations int number of iterations (default 50000)
-i, --iterations int number of iterations (default 50000) -s, --salt-size int salt size in bytes (default 16)
--no-confirm skip the password confirmation prompt -v, --variant string variant, options are sha256 and sha512 (default "sha512")
--password string manually supply the password rather than using the terminal prompt ```
--random uses a randomly generated password
--random.length int when using a randomly generated password it configures the length (default 72) ### Options inherited from parent commands
-s, --salt-size int salt size in bytes (default 16)
-v, --variant string variant, options are sha256 and sha512 (default "sha512") ```
-c, --config strings configuration files to load (default [configuration.yml])
--no-confirm skip the password confirmation prompt
--password string manually supply the password rather than using the terminal prompt
--random uses a randomly generated password
--random.characters string sets the explicit characters for the random string
--random.charset string sets the charset for the random password, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex' (default "alphanumeric")
--random.length int when using a randomly generated password it configures the length (default 72)
``` ```
### SEE ALSO ### SEE ALSO

View File

@ -43,10 +43,10 @@ authelia crypto rand --characters 0123456789ABCDEF
### Options ### Options
``` ```
--characters string Sets the explicit characters for the random output --characters string Sets the explicit characters for the random string
-c, --charset string Sets the charset for the output, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex' (default "alphanumeric") -c, --charset string Sets the charset for the random string, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex' (default "alphanumeric")
-h, --help help for rand -h, --help help for rand
-n, --length int Sets the length of the random output (default 80) -n, --length int Sets the length of the random output (default 72)
``` ```
### SEE ALSO ### SEE ALSO

View File

@ -529,21 +529,23 @@ const (
cmdFlagNameBits = "bits" cmdFlagNameBits = "bits"
cmdFlagNameCurve = "curve" cmdFlagNameCurve = "curve"
cmdFlagNamePassword = "password" cmdFlagNamePassword = "password"
cmdFlagNameRandom = "random" cmdFlagNameRandom = "random"
cmdFlagNameRandomLength = "random.length" cmdFlagNameRandomLength = "random.length"
cmdFlagNameNoConfirm = "no-confirm" cmdFlagNameRandomCharSet = "random.charset"
cmdFlagNameVariant = "variant" cmdFlagNameRandomCharacters = "random.characters"
cmdFlagNameCost = "cost" cmdFlagNameNoConfirm = "no-confirm"
cmdFlagNameIterations = "iterations" cmdFlagNameVariant = "variant"
cmdFlagNameParallelism = "parallelism" cmdFlagNameCost = "cost"
cmdFlagNameBlockSize = "block-size" cmdFlagNameIterations = "iterations"
cmdFlagNameMemory = "memory" cmdFlagNameParallelism = "parallelism"
cmdFlagNameKeySize = "key-size" cmdFlagNameBlockSize = "block-size"
cmdFlagNameSaltSize = "salt-size" cmdFlagNameMemory = "memory"
cmdFlagNameProfile = "profile" cmdFlagNameKeySize = "key-size"
cmdFlagNameSHA512 = "sha512" cmdFlagNameSaltSize = "salt-size"
cmdFlagNameConfig = "config" cmdFlagNameProfile = "profile"
cmdFlagNameSHA512 = "sha512"
cmdFlagNameConfig = "config"
cmdFlagNameCharSet = "charset" cmdFlagNameCharSet = "charset"
cmdFlagNameCharacters = "characters" cmdFlagNameCharacters = "characters"

View File

@ -44,53 +44,15 @@ func newCryptoRandCmd() (cmd *cobra.Command) {
Example: cmdAutheliaCryptoRandExample, Example: cmdAutheliaCryptoRandExample,
Args: cobra.NoArgs, Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) (err error) { RunE: func(cmd *cobra.Command, args []string) (err error) {
useCharSet, useCharacters := cmd.Flags().Changed(cmdFlagNameCharSet), cmd.Flags().Changed(cmdFlagNameCharacters)
if useCharSet && useCharacters {
return fmt.Errorf("flags '--%s' and '--%s' are mutually exclusive, only one may be specified", cmdFlagNameCharSet, cmdFlagNameCharacters)
}
var ( var (
charset string random string
n int
) )
if n, err = cmd.Flags().GetInt(cmdFlagNameLength); err != nil { if random, err = flagsGetRandomCharacters(cmd.Flags(), cmdFlagNameLength, cmdFlagNameCharSet, cmdFlagNameCharacters); err != nil {
return err return err
} }
if n < 1 { fmt.Printf("Random Value: %s\n", random)
return fmt.Errorf("length must be at least 1")
}
switch {
case useCharSet, !useCharSet && !useCharacters:
var c string
if c, err = cmd.Flags().GetString(cmdFlagNameCharSet); err != nil {
return err
}
switch c {
case "ascii":
charset = utils.CharSetASCII
case "alphanumeric":
charset = utils.CharSetAlphaNumeric
case "alphabetic":
charset = utils.CharSetAlphabetic
case "numeric-hex":
charset = utils.CharSetNumericHex
case "numeric":
charset = utils.CharSetNumeric
default:
return fmt.Errorf("invalid charset '%s', must be one of 'ascii', 'alphanumeric', 'alphabetic', 'numeric', or 'numeric-hex'", c)
}
case useCharacters:
if charset, err = cmd.Flags().GetString(cmdFlagNameCharacters); err != nil {
return err
}
}
fmt.Printf("Random Value: %s\n", utils.RandomString(n, charset, true))
return nil return nil
}, },
@ -98,9 +60,9 @@ func newCryptoRandCmd() (cmd *cobra.Command) {
DisableAutoGenTag: true, DisableAutoGenTag: true,
} }
cmd.Flags().StringP(cmdFlagNameCharSet, "c", "alphanumeric", "Sets the charset for the output, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex'") cmd.Flags().StringP(cmdFlagNameCharSet, "c", "alphanumeric", "Sets the charset for the random string, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex'")
cmd.Flags().String(cmdFlagNameCharacters, "", "Sets the explicit characters for the random output") cmd.Flags().String(cmdFlagNameCharacters, "", "Sets the explicit characters for the random string")
cmd.Flags().IntP(cmdFlagNameLength, "n", 80, "Sets the length of the random output") cmd.Flags().IntP(cmdFlagNameLength, "n", 72, "Sets the length of the random output")
return cmd return cmd
} }

View File

@ -14,7 +14,6 @@ import (
"github.com/authelia/authelia/v4/internal/configuration" "github.com/authelia/authelia/v4/internal/configuration"
"github.com/authelia/authelia/v4/internal/configuration/schema" "github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/configuration/validator" "github.com/authelia/authelia/v4/internal/configuration/validator"
"github.com/authelia/authelia/v4/internal/utils"
) )
func newHashPasswordCmd() (cmd *cobra.Command) { func newHashPasswordCmd() (cmd *cobra.Command) {
@ -105,6 +104,7 @@ func newCryptoHashGenerateCmd() (cmd *cobra.Command) {
cmdFlagConfig(cmd) cmdFlagConfig(cmd)
cmdFlagPassword(cmd, true) cmdFlagPassword(cmd, true)
cmdFlagRandomPassword(cmd)
for _, use := range []string{cmdUseHashArgon2, cmdUseHashSHA2Crypt, cmdUseHashPBKDF2, cmdUseHashBCrypt, cmdUseHashSCrypt} { for _, use := range []string{cmdUseHashArgon2, cmdUseHashSHA2Crypt, cmdUseHashPBKDF2, cmdUseHashBCrypt, cmdUseHashSCrypt} {
cmd.AddCommand(newCryptoHashGenerateSubCmd(use)) cmd.AddCommand(newCryptoHashGenerateSubCmd(use))
@ -129,10 +129,6 @@ func newCryptoHashGenerateSubCmd(use string) (cmd *cobra.Command) {
DisableAutoGenTag: true, DisableAutoGenTag: true,
} }
cmdFlagConfig(cmd)
cmdFlagPassword(cmd, true)
cmdFlagRandomPassword(cmd)
switch use { switch use {
case cmdUseHashArgon2: case cmdUseHashArgon2:
cmdFlagIterations(cmd, schema.DefaultPasswordConfig.Argon2.Iterations) cmdFlagIterations(cmd, schema.DefaultPasswordConfig.Argon2.Iterations)
@ -419,13 +415,7 @@ func cmdCryptoHashGetPassword(cmd *cobra.Command, args []string, useArgs, useRan
switch { switch {
case random: case random:
var length int password, err = flagsGetRandomCharacters(cmd.Flags(), cmdFlagNameRandomLength, cmdFlagNameRandomCharSet, cmdFlagNameCharacters)
if length, err = cmd.Flags().GetInt(cmdFlagNameRandomLength); err != nil {
return
}
password = utils.RandomString(length, utils.CharSetAlphaNumeric, true)
return return
case cmd.Flags().Changed(cmdFlagNamePassword): case cmd.Flags().Changed(cmdFlagNamePassword):
@ -494,20 +484,22 @@ func hashReadPasswordWithPrompt(prompt string) (data []byte, err error) {
} }
func cmdFlagConfig(cmd *cobra.Command) { func cmdFlagConfig(cmd *cobra.Command) {
cmd.Flags().StringSliceP(cmdFlagNameConfig, "c", []string{"configuration.yml"}, "configuration files to load") cmd.PersistentFlags().StringSliceP(cmdFlagNameConfig, "c", []string{"configuration.yml"}, "configuration files to load")
} }
func cmdFlagPassword(cmd *cobra.Command, noConfirm bool) { func cmdFlagPassword(cmd *cobra.Command, noConfirm bool) {
cmd.Flags().String(cmdFlagNamePassword, "", "manually supply the password rather than using the terminal prompt") cmd.PersistentFlags().String(cmdFlagNamePassword, "", "manually supply the password rather than using the terminal prompt")
if noConfirm { if noConfirm {
cmd.Flags().Bool(cmdFlagNameNoConfirm, false, "skip the password confirmation prompt") cmd.PersistentFlags().Bool(cmdFlagNameNoConfirm, false, "skip the password confirmation prompt")
} }
} }
func cmdFlagRandomPassword(cmd *cobra.Command) { func cmdFlagRandomPassword(cmd *cobra.Command) {
cmd.Flags().Bool(cmdFlagNameRandom, false, "uses a randomly generated password") cmd.PersistentFlags().Bool(cmdFlagNameRandom, false, "uses a randomly generated password")
cmd.Flags().Int(cmdFlagNameRandomLength, 72, "when using a randomly generated password it configures the length") cmd.PersistentFlags().Int(cmdFlagNameRandomLength, 72, "when using a randomly generated password it configures the length")
cmd.PersistentFlags().String(cmdFlagNameRandomCharSet, "alphanumeric", "sets the charset for the random password, options are 'ascii', 'alphanumeric', 'alphabetic', 'numeric', and 'numeric-hex'")
cmd.PersistentFlags().String(cmdFlagNameRandomCharacters, "", "sets the explicit characters for the random string")
} }
func cmdFlagIterations(cmd *cobra.Command, value int) { func cmdFlagIterations(cmd *cobra.Command, value int) {

View File

@ -3,6 +3,10 @@ package commands
import ( import (
"fmt" "fmt"
"os" "os"
"github.com/spf13/pflag"
"github.com/authelia/authelia/v4/internal/utils"
) )
func recoverErr(i any) error { func recoverErr(i any) error {
@ -29,3 +33,54 @@ func configFilterExisting(configs []string) (finalConfigs []string) {
return finalConfigs return finalConfigs
} }
func flagsGetRandomCharacters(flags *pflag.FlagSet, flagNameLength, flagNameCharSet, flagNameCharacters string) (r string, err error) {
var (
n int
charset string
)
if n, err = flags.GetInt(flagNameLength); err != nil {
return "", err
}
if n < 1 {
return "", fmt.Errorf("flag --%s with value '%d' is invalid: must be at least 1", flagNameLength, n)
}
useCharSet, useCharacters := flags.Changed(flagNameCharSet), flags.Changed(flagNameCharacters)
if useCharSet && useCharacters {
return "", fmt.Errorf("flag --%s and flag --%s are mutually exclusive, only one may be used", flagNameCharSet, flagNameCharacters)
}
switch {
case useCharSet, !useCharSet && !useCharacters:
var c string
if c, err = flags.GetString(flagNameCharSet); err != nil {
return "", err
}
switch c {
case "ascii":
charset = utils.CharSetASCII
case "alphanumeric":
charset = utils.CharSetAlphaNumeric
case "alphabetic":
charset = utils.CharSetAlphabetic
case "numeric-hex":
charset = utils.CharSetNumericHex
case "numeric":
charset = utils.CharSetNumeric
default:
return "", fmt.Errorf("flag '--%s' with value '%s' is invalid, must be one of 'ascii', 'alphanumeric', 'alphabetic', 'numeric', or 'numeric-hex'", flagNameCharSet, c)
}
case useCharacters:
if charset, err = flags.GetString(flagNameCharacters); err != nil {
return "", err
}
}
return utils.RandomString(n, charset, true), nil
}

View File

@ -49,7 +49,7 @@ func init() {
SetUp: setup, SetUp: setup,
SetUpTimeout: 5 * time.Minute, SetUpTimeout: 5 * time.Minute,
OnSetupTimeout: displayAutheliaLogs, OnSetupTimeout: displayAutheliaLogs,
TestTimeout: 2 * time.Minute, TestTimeout: 3 * time.Minute,
TearDown: teardown, TearDown: teardown,
TearDownTimeout: 2 * time.Minute, TearDownTimeout: 2 * time.Minute,
}) })

View File

@ -64,7 +64,7 @@ func init() {
SetUpTimeout: 5 * time.Minute, SetUpTimeout: 5 * time.Minute,
OnSetupTimeout: displayAutheliaLogs, OnSetupTimeout: displayAutheliaLogs,
OnError: displayAutheliaLogs, OnError: displayAutheliaLogs,
TestTimeout: 3 * time.Minute, TestTimeout: 4 * time.Minute,
TearDown: teardown, TearDown: teardown,
TearDownTimeout: 2 * time.Minute, TearDownTimeout: 2 * time.Minute,