mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
feat(commands): totp qr code in png format (#2673)
This allows exporting the TOTP QR code for easy registration when using `authelia storage totp generate` or `authelia storage totp export`.
This commit is contained in:
parent
6276883f04
commit
1b2af90e5a
|
@ -105,6 +105,7 @@ const (
|
|||
const (
|
||||
storageExportFormatCSV = "csv"
|
||||
storageExportFormatURI = "uri"
|
||||
storageExportFormatPNG = "png"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -112,6 +112,7 @@ func newStorageTOTPGenerateCmd() (cmd *cobra.Command) {
|
|||
cmd.Flags().String("algorithm", "SHA1", "set the TOTP algorithm")
|
||||
cmd.Flags().String("issuer", "Authelia", "set the TOTP issuer")
|
||||
cmd.Flags().BoolP("force", "f", false, "forces the TOTP configuration to be generated regardless if it exists or not")
|
||||
cmd.Flags().StringP("path", "p", "", "path to a file to create a PNG file with the QR code (optional)")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -135,6 +136,7 @@ func newStorageTOTPExportCmd() (cmd *cobra.Command) {
|
|||
}
|
||||
|
||||
cmd.Flags().String("format", storageExportFormatURI, "sets the output format")
|
||||
cmd.Flags().String("dir", "", "used with the png output format to specify which new directory to save the files in")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/png"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -15,11 +18,13 @@ import (
|
|||
"github.com/authelia/authelia/v4/internal/models"
|
||||
"github.com/authelia/authelia/v4/internal/storage"
|
||||
"github.com/authelia/authelia/v4/internal/totp"
|
||||
"github.com/authelia/authelia/v4/internal/utils"
|
||||
)
|
||||
|
||||
func storagePersistentPreRunE(cmd *cobra.Command, _ []string) (err error) {
|
||||
configs, err := cmd.Flags().GetStringSlice("config")
|
||||
if err != nil {
|
||||
var configs []string
|
||||
|
||||
if configs, err = cmd.Flags().GetStringSlice("config"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -72,8 +77,7 @@ func storagePersistentPreRunE(cmd *cobra.Command, _ []string) (err error) {
|
|||
|
||||
config = &schema.Configuration{}
|
||||
|
||||
_, err = configuration.LoadAdvanced(val, "", &config, sources...)
|
||||
if err != nil {
|
||||
if _, err = configuration.LoadAdvanced(val, "", &config, sources...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -117,7 +121,9 @@ func storagePersistentPreRunE(cmd *cobra.Command, _ []string) (err error) {
|
|||
func storageSchemaEncryptionCheckRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
var (
|
||||
provider storage.Provider
|
||||
ctx = context.Background()
|
||||
verbose bool
|
||||
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
provider = getStorageProvider()
|
||||
|
@ -126,8 +132,7 @@ func storageSchemaEncryptionCheckRunE(cmd *cobra.Command, args []string) (err er
|
|||
_ = provider.Close()
|
||||
}()
|
||||
|
||||
verbose, err := cmd.Flags().GetBool("verbose")
|
||||
if err != nil {
|
||||
if verbose, err = cmd.Flags().GetBool("verbose"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -150,7 +155,10 @@ func storageSchemaEncryptionCheckRunE(cmd *cobra.Command, args []string) (err er
|
|||
func storageSchemaEncryptionChangeKeyRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
var (
|
||||
provider storage.Provider
|
||||
ctx = context.Background()
|
||||
key string
|
||||
version int
|
||||
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
provider = getStorageProvider()
|
||||
|
@ -163,8 +171,7 @@ func storageSchemaEncryptionChangeKeyRunE(cmd *cobra.Command, args []string) (er
|
|||
return err
|
||||
}
|
||||
|
||||
version, err := provider.SchemaVersion(ctx)
|
||||
if err != nil {
|
||||
if version, err = provider.SchemaVersion(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -172,17 +179,15 @@ func storageSchemaEncryptionChangeKeyRunE(cmd *cobra.Command, args []string) (er
|
|||
return errors.New("schema version must be at least version 1 to change the encryption key")
|
||||
}
|
||||
|
||||
key, err := cmd.Flags().GetString("new-encryption-key")
|
||||
if err != nil {
|
||||
key, err = cmd.Flags().GetString("new-encryption-key")
|
||||
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
}
|
||||
|
||||
if key == "" {
|
||||
case key == "":
|
||||
return errors.New("you must set the --new-encryption-key flag")
|
||||
}
|
||||
|
||||
if len(key) < 20 {
|
||||
return errors.New("the encryption key must be at least 20 characters")
|
||||
case len(key) < 20:
|
||||
return errors.New("the new encryption key must be at least 20 characters")
|
||||
}
|
||||
|
||||
if err = provider.SchemaEncryptionChangeKey(ctx, key); err != nil {
|
||||
|
@ -200,6 +205,9 @@ func storageTOTPGenerateRunE(cmd *cobra.Command, args []string) (err error) {
|
|||
ctx = context.Background()
|
||||
c *models.TOTPConfiguration
|
||||
force bool
|
||||
filename string
|
||||
file *os.File
|
||||
img image.Image
|
||||
)
|
||||
|
||||
provider = getStorageProvider()
|
||||
|
@ -208,10 +216,15 @@ func storageTOTPGenerateRunE(cmd *cobra.Command, args []string) (err error) {
|
|||
_ = provider.Close()
|
||||
}()
|
||||
|
||||
force, err = cmd.Flags().GetBool("force")
|
||||
if force, err = cmd.Flags().GetBool("force"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = provider.LoadTOTPConfiguration(ctx, args[0])
|
||||
if err == nil && !force {
|
||||
if filename, err = cmd.Flags().GetString("path"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = provider.LoadTOTPConfiguration(ctx, args[0]); err == nil && !force {
|
||||
return fmt.Errorf("%s already has a TOTP configuration, use --force to overwrite", args[0])
|
||||
}
|
||||
|
||||
|
@ -225,12 +238,35 @@ func storageTOTPGenerateRunE(cmd *cobra.Command, args []string) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
err = provider.SaveTOTPConfiguration(ctx, *c)
|
||||
if err != nil {
|
||||
extraInfo := ""
|
||||
|
||||
if filename != "" {
|
||||
if _, err = os.Stat(filename); !os.IsNotExist(err) {
|
||||
return errors.New("image output filepath already exists")
|
||||
}
|
||||
|
||||
if file, err = os.Create(filename); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
if img, err = c.Image(256, 256); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = png.Encode(file, img); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
extraInfo = fmt.Sprintf(" and saved it as a PNG image at the path '%s'", filename)
|
||||
}
|
||||
|
||||
if err = provider.SaveTOTPConfiguration(ctx, *c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Generated TOTP configuration for user '%s': %s", args[0], c.URI())
|
||||
fmt.Printf("Generated TOTP configuration for user '%s' with URI '%s'%s\n", args[0], c.URI(), extraInfo)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -249,13 +285,11 @@ func storageTOTPDeleteRunE(cmd *cobra.Command, args []string) (err error) {
|
|||
_ = provider.Close()
|
||||
}()
|
||||
|
||||
_, err = provider.LoadTOTPConfiguration(ctx, user)
|
||||
if err != nil {
|
||||
if _, err = provider.LoadTOTPConfiguration(ctx, user); err != nil {
|
||||
return fmt.Errorf("can't delete configuration for user '%s': %+v", user, err)
|
||||
}
|
||||
|
||||
err = provider.DeleteTOTPConfiguration(ctx, user)
|
||||
if err != nil {
|
||||
if err = provider.DeleteTOTPConfiguration(ctx, user); err != nil {
|
||||
return fmt.Errorf("can't delete configuration for user '%s': %+v", user, err)
|
||||
}
|
||||
|
||||
|
@ -266,8 +300,12 @@ func storageTOTPDeleteRunE(cmd *cobra.Command, args []string) (err error) {
|
|||
|
||||
func storageTOTPExportRunE(cmd *cobra.Command, args []string) (err error) {
|
||||
var (
|
||||
provider storage.Provider
|
||||
ctx = context.Background()
|
||||
provider storage.Provider
|
||||
format, dir string
|
||||
configurations []models.TOTPConfiguration
|
||||
img image.Image
|
||||
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
provider = getStorageProvider()
|
||||
|
@ -280,25 +318,14 @@ func storageTOTPExportRunE(cmd *cobra.Command, args []string) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
format, err := cmd.Flags().GetString("format")
|
||||
if err != nil {
|
||||
if format, dir, err = storageTOTPExportGetConfigFromFlags(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch format {
|
||||
case storageExportFormatCSV, storageExportFormatURI:
|
||||
break
|
||||
default:
|
||||
return errors.New("format must be csv or uri")
|
||||
}
|
||||
|
||||
limit := 10
|
||||
|
||||
var configurations []models.TOTPConfiguration
|
||||
|
||||
for page := 0; true; page++ {
|
||||
configurations, err = provider.LoadTOTPConfigurations(ctx, limit, page)
|
||||
if err != nil {
|
||||
if configurations, err = provider.LoadTOTPConfigurations(ctx, limit, page); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -312,6 +339,17 @@ func storageTOTPExportRunE(cmd *cobra.Command, args []string) (err error) {
|
|||
fmt.Printf("%s,%s,%s,%d,%d,%s\n", c.Issuer, c.Username, c.Algorithm, c.Digits, c.Period, string(c.Secret))
|
||||
case storageExportFormatURI:
|
||||
fmt.Println(c.URI())
|
||||
case storageExportFormatPNG:
|
||||
file, _ := os.Create(filepath.Join(dir, fmt.Sprintf("%s.png", c.Username)))
|
||||
defer file.Close()
|
||||
|
||||
if img, err = c.Image(256, 256); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = png.Encode(file, img); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,13 +358,51 @@ func storageTOTPExportRunE(cmd *cobra.Command, args []string) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if format == storageExportFormatPNG {
|
||||
fmt.Printf("Exported TOTP QR codes in PNG format in the '%s' directory\n", dir)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func storageTOTPExportGetConfigFromFlags(cmd *cobra.Command) (format, dir string, err error) {
|
||||
if format, err = cmd.Flags().GetString("format"); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
if dir, err = cmd.Flags().GetString("dir"); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
switch format {
|
||||
case storageExportFormatCSV, storageExportFormatURI:
|
||||
break
|
||||
case storageExportFormatPNG:
|
||||
if dir == "" {
|
||||
dir = utils.RandomString(8, utils.AlphaNumericCharacters, false)
|
||||
}
|
||||
|
||||
if _, err = os.Stat(dir); !os.IsNotExist(err) {
|
||||
return "", "", errors.New("output directory must not exist")
|
||||
}
|
||||
|
||||
if err = os.MkdirAll(dir, 0700); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
default:
|
||||
return "", "", errors.New("format must be csv, uri, or png")
|
||||
}
|
||||
|
||||
return format, dir, nil
|
||||
}
|
||||
|
||||
func storageMigrateHistoryRunE(_ *cobra.Command, _ []string) (err error) {
|
||||
var (
|
||||
provider storage.Provider
|
||||
ctx = context.Background()
|
||||
provider storage.Provider
|
||||
version int
|
||||
migrations []models.Migration
|
||||
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
provider = getStorageProvider()
|
||||
|
@ -338,8 +414,7 @@ func storageMigrateHistoryRunE(_ *cobra.Command, _ []string) (err error) {
|
|||
_ = provider.Close()
|
||||
}()
|
||||
|
||||
version, err := provider.SchemaVersion(ctx)
|
||||
if err != nil {
|
||||
if version, err = provider.SchemaVersion(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -348,8 +423,7 @@ func storageMigrateHistoryRunE(_ *cobra.Command, _ []string) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
migrations, err := provider.SchemaMigrationHistory(ctx)
|
||||
if err != nil {
|
||||
if migrations, err = provider.SchemaMigrationHistory(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -411,7 +485,10 @@ func newStorageMigrationRunE(up bool) func(cmd *cobra.Command, args []string) (e
|
|||
return func(cmd *cobra.Command, args []string) (err error) {
|
||||
var (
|
||||
provider storage.Provider
|
||||
ctx = context.Background()
|
||||
target int
|
||||
pre1 bool
|
||||
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
provider = getStorageProvider()
|
||||
|
@ -420,8 +497,7 @@ func newStorageMigrationRunE(up bool) func(cmd *cobra.Command, args []string) (e
|
|||
_ = provider.Close()
|
||||
}()
|
||||
|
||||
target, err := cmd.Flags().GetInt("target")
|
||||
if err != nil {
|
||||
if target, err = cmd.Flags().GetInt("target"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -434,8 +510,7 @@ func newStorageMigrationRunE(up bool) func(cmd *cobra.Command, args []string) (e
|
|||
return provider.SchemaMigrate(ctx, true, storage.SchemaLatest)
|
||||
}
|
||||
default:
|
||||
pre1, err := cmd.Flags().GetBool("pre1")
|
||||
if err != nil {
|
||||
if pre1, err = cmd.Flags().GetBool("pre1"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -458,8 +533,9 @@ func newStorageMigrationRunE(up bool) func(cmd *cobra.Command, args []string) (e
|
|||
}
|
||||
|
||||
func storageMigrateDownConfirmDestroy(cmd *cobra.Command) (err error) {
|
||||
destroy, err := cmd.Flags().GetBool("destroy-data")
|
||||
if err != nil {
|
||||
var destroy bool
|
||||
|
||||
if destroy, err = cmd.Flags().GetBool("destroy-data"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -480,10 +556,13 @@ func storageMigrateDownConfirmDestroy(cmd *cobra.Command) (err error) {
|
|||
|
||||
func storageSchemaInfoRunE(_ *cobra.Command, _ []string) (err error) {
|
||||
var (
|
||||
provider storage.Provider
|
||||
ctx = context.Background()
|
||||
upgradeStr string
|
||||
tablesStr string
|
||||
upgradeStr, tablesStr string
|
||||
|
||||
provider storage.Provider
|
||||
tables []string
|
||||
version, latest int
|
||||
|
||||
ctx = context.Background()
|
||||
)
|
||||
|
||||
provider = getStorageProvider()
|
||||
|
@ -492,13 +571,11 @@ func storageSchemaInfoRunE(_ *cobra.Command, _ []string) (err error) {
|
|||
_ = provider.Close()
|
||||
}()
|
||||
|
||||
version, err := provider.SchemaVersion(ctx)
|
||||
if err != nil && err.Error() != "unknown schema state" {
|
||||
if version, err = provider.SchemaVersion(ctx); err != nil && err.Error() != "unknown schema state" {
|
||||
return err
|
||||
}
|
||||
|
||||
tables, err := provider.SchemaTables(ctx)
|
||||
if err != nil {
|
||||
if tables, err = provider.SchemaTables(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -508,8 +585,7 @@ func storageSchemaInfoRunE(_ *cobra.Command, _ []string) (err error) {
|
|||
tablesStr = strings.Join(tables, ", ")
|
||||
}
|
||||
|
||||
latest, err := provider.SchemaLatestVersion()
|
||||
if err != nil {
|
||||
if latest, err = provider.SchemaLatestVersion(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -537,13 +613,13 @@ func storageSchemaInfoRunE(_ *cobra.Command, _ []string) (err error) {
|
|||
}
|
||||
|
||||
func checkStorageSchemaUpToDate(ctx context.Context, provider storage.Provider) (err error) {
|
||||
version, err := provider.SchemaVersion(ctx)
|
||||
if err != nil {
|
||||
var version, latest int
|
||||
|
||||
if version, err = provider.SchemaVersion(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
latest, err := provider.SchemaLatestVersion()
|
||||
if err != nil {
|
||||
if latest, err = provider.SchemaLatestVersion(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"image"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/pquerna/otp"
|
||||
)
|
||||
|
||||
// TOTPConfiguration represents a users TOTP configuration row in the database.
|
||||
|
@ -34,3 +37,19 @@ func (c TOTPConfiguration) URI() (uri string) {
|
|||
|
||||
return u.String()
|
||||
}
|
||||
|
||||
// Key returns the *otp.Key using TOTPConfiguration.URI with otp.NewKeyFromURL.
|
||||
func (c TOTPConfiguration) Key() (key *otp.Key, err error) {
|
||||
return otp.NewKeyFromURL(c.URI())
|
||||
}
|
||||
|
||||
// Image returns the image.Image of the TOTPConfiguration using the Image func from the return of TOTPConfiguration.Key.
|
||||
func (c TOTPConfiguration) Image(width, height int) (img image.Image, err error) {
|
||||
var key *otp.Key
|
||||
|
||||
if key, err = c.Key(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return key.Image(width, height)
|
||||
}
|
||||
|
|
|
@ -38,3 +38,40 @@ func TestShouldOnlyMarshalPeriodAndDigitsAndAbsolutelyNeverSecret(t *testing.T)
|
|||
require.NotContains(t, string(data), "secret")
|
||||
require.NotContains(t, string(data), "ABC123")
|
||||
}
|
||||
|
||||
func TestShouldReturnErrWhenImageTooSmall(t *testing.T) {
|
||||
object := TOTPConfiguration{
|
||||
ID: 1,
|
||||
Username: "john",
|
||||
Issuer: "Authelia",
|
||||
Algorithm: "SHA1",
|
||||
Digits: 6,
|
||||
Period: 30,
|
||||
Secret: []byte("ABC123"),
|
||||
}
|
||||
|
||||
img, err := object.Image(10, 10)
|
||||
|
||||
assert.EqualError(t, err, "can not scale barcode to an image smaller than 41x41")
|
||||
assert.Nil(t, img)
|
||||
}
|
||||
|
||||
func TestShouldReturnImage(t *testing.T) {
|
||||
object := TOTPConfiguration{
|
||||
ID: 1,
|
||||
Username: "john",
|
||||
Issuer: "Authelia",
|
||||
Algorithm: "SHA1",
|
||||
Digits: 6,
|
||||
Period: 30,
|
||||
Secret: []byte("ABC123"),
|
||||
}
|
||||
|
||||
img, err := object.Image(41, 41)
|
||||
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, img)
|
||||
|
||||
assert.Equal(t, 41, img.Bounds().Dx())
|
||||
assert.Equal(t, 41, img.Bounds().Dy())
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ func init() {
|
|||
err := dockerEnvironment.Down()
|
||||
_ = os.Remove("/tmp/db.sqlite3")
|
||||
_ = os.Remove("/tmp/db.sqlite")
|
||||
_ = os.RemoveAll("/tmp/qr/")
|
||||
_ = os.Remove("/tmp/qr.png")
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -66,13 +66,13 @@ func (s *CLISuite) TestShouldPrintVersion() {
|
|||
}
|
||||
|
||||
func (s *CLISuite) TestShouldValidateConfig() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "validate-config", "--config", "/config/configuration.yml"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "validate-config", "--config=/config/configuration.yml"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Configuration parsed and loaded successfully without errors.")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldFailValidateConfig() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "validate-config", "--config", "/config/invalid.yml"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "validate-config", "--config=/config/invalid.yml"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "failed to load configuration from yaml file(/config/invalid.yml) source: open /config/invalid.yml: no such file or directory")
|
||||
}
|
||||
|
@ -90,75 +90,75 @@ func (s *CLISuite) TestShouldHashPasswordSHA512() {
|
|||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateRSA() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateRSAWithIPAddress() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "127.0.0.1", "--dir", "/tmp/"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=127.0.0.1", "--dir=/tmp/"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateRSAWithStartDate() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--start-date", "'Jan 1 15:04:05 2011'"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--start-date='Jan 1 15:04:05 2011'"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldFailGenerateCertificateRSAWithStartDate() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--start-date", "Jan"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--start-date=Jan"})
|
||||
s.Assert().NotNil(err)
|
||||
s.Assert().Contains(output, "Failed to parse start date: parsing time \"Jan\" as \"Jan 2 15:04:05 2006\": cannot parse \"\" as \"2\"")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateCA() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--ca"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ca"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateEd25519() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--ed25519"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ed25519"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldFailGenerateCertificateECDSA() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--ecdsa-curve", "invalid"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=invalid"})
|
||||
s.Assert().NotNil(err)
|
||||
s.Assert().Contains(output, "Failed to generate private key: unrecognized elliptic curve: \"invalid\"")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateECDSAP224() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--ecdsa-curve", "P224"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=P224"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateECDSAP256() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--ecdsa-curve", "P256"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=P256"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateECDSAP384() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--ecdsa-curve", "P384"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=P384"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestShouldGenerateCertificateECDSAP521() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host", "*.example.com", "--dir", "/tmp/", "--ecdsa-curve", "P521"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=P521"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Certificate Public Key written to /tmp/cert.pem")
|
||||
s.Assert().Contains(output, "Certificate Private Key written to /tmp/key.pem")
|
||||
|
@ -179,7 +179,7 @@ func (s *CLISuite) TestStorageShouldShowErrWithoutConfig() {
|
|||
func (s *CLISuite) TestStorage00ShouldShowCorrectPreInitInformation() {
|
||||
_ = os.Remove("/tmp/db.sqlite3")
|
||||
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config", "/config/configuration.storage.yml"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
pattern := regexp.MustCompile(`^Schema Version: N/A\nSchema Upgrade Available: yes - version \d+\nSchema Tables: N/A\nSchema Encryption Key: unsupported \(schema version\)`)
|
||||
|
@ -188,45 +188,45 @@ func (s *CLISuite) TestStorage00ShouldShowCorrectPreInitInformation() {
|
|||
|
||||
patternOutdated := regexp.MustCompile(`Error: schema is version \d+ which is outdated please migrate to version \d+ in order to use this command or use an older binary`)
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "export", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "export", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
s.Assert().Regexp(patternOutdated, output)
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
s.Assert().Regexp(patternOutdated, output)
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Could not check encryption key for validity. The schema version doesn't support encryption.")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "down", "--target", "0", "--destroy-data", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "down", "--target=0", "--destroy-data", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
s.Assert().Contains(output, "Error: schema migration target version 0 is the same current version 0")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "up", "--target", "2147483640", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "up", "--target=2147483640", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
s.Assert().Contains(output, "Error: schema up migration target version 2147483640 is greater then the latest version ")
|
||||
s.Assert().Contains(output, " which indicates it doesn't exist")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "--config", "/config/configuration.storage.yml", "migrate", "history"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "history", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "No migration history is available for schemas that not version 1 or above.\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "--config", "/config/configuration.storage.yml", "migrate", "list-up"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "list-up", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Storage Schema Migration List (Up)\n\nVersion\t\tDescription\n1\t\tInitial Schema\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "--config", "/config/configuration.storage.yml", "migrate", "list-down"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "list-down", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Storage Schema Migration List (Down)\n\nNo Migrations Available\n")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestStorage01ShouldMigrateUp() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "--config", "/config/configuration.storage.yml", "migrate", "up"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "up", "--config=/config/configuration.storage.yml"})
|
||||
s.Require().NoError(err)
|
||||
|
||||
pattern0 := regexp.MustCompile(`"Storage schema migration from \d+ to \d+ is being attempted"`)
|
||||
|
@ -235,23 +235,23 @@ func (s *CLISuite) TestStorage01ShouldMigrateUp() {
|
|||
s.Regexp(pattern0, output)
|
||||
s.Regexp(pattern1, output)
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "--config", "/config/configuration.storage.yml", "migrate", "up"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "up", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
|
||||
s.Assert().Contains(output, "Error: schema already up to date\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "--config", "/config/configuration.storage.yml", "migrate", "history"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "history", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Migration History:\n\nID\tDate\t\t\t\tBefore\tAfter\tAuthelia Version\n")
|
||||
s.Assert().Contains(output, "0\t1")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "--config", "/config/configuration.storage.yml", "migrate", "list-up"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "list-up", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Storage Schema Migration List (Up)\n\nNo Migrations Available")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "--config", "/config/configuration.storage.yml", "migrate", "list-down"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "list-down", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Storage Schema Migration List (Down)\n\nVersion\t\tDescription\n")
|
||||
|
@ -259,7 +259,7 @@ func (s *CLISuite) TestStorage01ShouldMigrateUp() {
|
|||
}
|
||||
|
||||
func (s *CLISuite) TestStorage02ShouldShowSchemaInfo() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config", "/config/configuration.storage.yml"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
pattern := regexp.MustCompile(`^Schema Version: \d+\nSchema Upgrade Available: no\nSchema Tables: authentication_logs, identity_verification, totp_configurations, u2f_devices, duo_devices, user_preferences, migrations, encryption\nSchema Encryption Key: valid`)
|
||||
|
@ -284,95 +284,157 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
|
|||
|
||||
expectedLinesCSV = append(expectedLinesCSV, "issuer,username,algorithm,digits,period,secret")
|
||||
|
||||
configs := []*models.TOTPConfiguration{
|
||||
testCases := []struct {
|
||||
config models.TOTPConfiguration
|
||||
png bool
|
||||
}{
|
||||
{
|
||||
Username: "john",
|
||||
Period: 30,
|
||||
Digits: 6,
|
||||
Algorithm: "SHA1",
|
||||
config: models.TOTPConfiguration{
|
||||
Username: "john",
|
||||
Period: 30,
|
||||
Digits: 6,
|
||||
Algorithm: "SHA1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Username: "mary",
|
||||
Period: 45,
|
||||
Digits: 6,
|
||||
Algorithm: "SHA1",
|
||||
config: models.TOTPConfiguration{
|
||||
Username: "mary",
|
||||
Period: 45,
|
||||
Digits: 6,
|
||||
Algorithm: "SHA1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Username: "fred",
|
||||
Period: 30,
|
||||
Digits: 8,
|
||||
Algorithm: "SHA1",
|
||||
config: models.TOTPConfiguration{
|
||||
Username: "fred",
|
||||
Period: 30,
|
||||
Digits: 8,
|
||||
Algorithm: "SHA1",
|
||||
},
|
||||
},
|
||||
{
|
||||
Username: "jone",
|
||||
Period: 30,
|
||||
Digits: 6,
|
||||
Algorithm: "SHA512",
|
||||
config: models.TOTPConfiguration{
|
||||
Username: "jone",
|
||||
Period: 30,
|
||||
Digits: 6,
|
||||
Algorithm: "SHA512",
|
||||
},
|
||||
png: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, config := range configs {
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "generate", config.Username, "--period", strconv.Itoa(int(config.Period)), "--algorithm", config.Algorithm, "--digits", strconv.Itoa(int(config.Digits)), "--config", "/config/configuration.storage.yml"})
|
||||
var (
|
||||
config *models.TOTPConfiguration
|
||||
fileInfo os.FileInfo
|
||||
)
|
||||
|
||||
for _, testCase := range testCases {
|
||||
if testCase.png {
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "generate", testCase.config.Username, "--period", strconv.Itoa(int(testCase.config.Period)), "--algorithm", testCase.config.Algorithm, "--digits", strconv.Itoa(int(testCase.config.Digits)), "--path=/tmp/qr.png", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, " and saved it as a PNG image at the path '/tmp/qr.png'")
|
||||
|
||||
fileInfo, err = os.Stat("/tmp/qr.png")
|
||||
s.Assert().NoError(err)
|
||||
s.Require().NotNil(fileInfo)
|
||||
s.Assert().False(fileInfo.IsDir())
|
||||
s.Assert().Greater(fileInfo.Size(), int64(1000))
|
||||
} else {
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "generate", testCase.config.Username, "--period", strconv.Itoa(int(testCase.config.Period)), "--algorithm", testCase.config.Algorithm, "--digits", strconv.Itoa(int(testCase.config.Digits)), "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
}
|
||||
|
||||
config, err = storageProvider.LoadTOTPConfiguration(ctx, testCase.config.Username)
|
||||
s.Assert().NoError(err)
|
||||
|
||||
config, err = storageProvider.LoadTOTPConfiguration(ctx, config.Username)
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, config.URI())
|
||||
|
||||
expectedLinesCSV = append(expectedLinesCSV, fmt.Sprintf("%s,%s,%s,%d,%d,%s", "Authelia", config.Username, config.Algorithm, config.Digits, config.Period, string(config.Secret)))
|
||||
expectedLines = append(expectedLines, config.URI())
|
||||
}
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "export", "--format", "uri", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "export", "--format=uri", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
for _, expectedLine := range expectedLines {
|
||||
s.Assert().Contains(output, expectedLine)
|
||||
}
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "export", "--format", "csv", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "export", "--format=csv", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
for _, expectedLine := range expectedLinesCSV {
|
||||
s.Assert().Contains(output, expectedLine)
|
||||
}
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "export", "--format=wrong", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
s.Assert().Contains(output, "Error: format must be csv, uri, or png")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "export", "--format=png", "--dir=/tmp/qr", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
s.Assert().Contains(output, "Exported TOTP QR codes in PNG format in the '/tmp/qr' directory")
|
||||
|
||||
for _, testCase := range testCases {
|
||||
fileInfo, err = os.Stat(fmt.Sprintf("/tmp/qr/%s.png", testCase.config.Username))
|
||||
|
||||
s.Assert().NoError(err)
|
||||
s.Require().NotNil(fileInfo)
|
||||
|
||||
s.Assert().False(fileInfo.IsDir())
|
||||
s.Assert().Greater(fileInfo.Size(), int64(1000))
|
||||
}
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "totp", "generate", "test", "--period=30", "--algorithm=SHA1", "--digits=6", "--path=/tmp/qr.png", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
s.Assert().Contains(output, "Error: image output filepath already exists")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestStorage04ShouldChangeEncryptionKey() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--new-encryption-key", "apple-apple-apple-apple", "--config", "/config/configuration.storage.yml"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--new-encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Completed the encryption key change. Please adjust your configuration to use the new key.\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
pattern := regexp.MustCompile(`Schema Version: \d+\nSchema Upgrade Available: no\nSchema Tables: authentication_logs, identity_verification, totp_configurations, u2f_devices, duo_devices, user_preferences, migrations, encryption\nSchema Encryption Key: invalid`)
|
||||
s.Assert().Regexp(pattern, output)
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Encryption key validation: failed.\n\nError: the encryption key is not valid against the schema check value.\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--verbose", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--verbose", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Encryption key validation: failed.\n\nError: the encryption key is not valid against the schema check value, 4 of 4 total TOTP secrets were invalid.\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--encryption-key", "apple-apple-apple-apple", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Encryption key validation: success.\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--verbose", "--encryption-key", "apple-apple-apple-apple", "--config", "/config/configuration.storage.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--verbose", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
s.Assert().Contains(output, "Encryption key validation: success.\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
|
||||
s.Assert().Contains(output, "Error: you must set the --new-encryption-key flag\n")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--encryption-key=apple-apple-apple-apple", "--new-encryption-key=abc", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().EqualError(err, "exit status 1")
|
||||
|
||||
s.Assert().Contains(output, "Error: the new encryption key must be at least 20 characters\n")
|
||||
}
|
||||
|
||||
func (s *CLISuite) TestStorage05ShouldMigrateDown() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "down", "--target", "0", "--destroy-data", "--config", "/config/configuration.storage.yml"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "down", "--target=0", "--destroy-data", "--config=/config/configuration.storage.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
pattern0 := regexp.MustCompile(`"Storage schema migration from \d+ to \d+ is being attempted"`)
|
||||
|
@ -383,7 +445,7 @@ func (s *CLISuite) TestStorage05ShouldMigrateDown() {
|
|||
}
|
||||
|
||||
func (s *CLISuite) TestACLPolicyCheckVerbose() {
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://public.example.com", "--verbose", "--config", "/config/configuration.yml"})
|
||||
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://public.example.com", "--verbose", "--config=/config/configuration.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
// This is an example of `authelia access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://public.example.com --verbose`.
|
||||
|
@ -400,7 +462,7 @@ func (s *CLISuite) TestACLPolicyCheckVerbose() {
|
|||
s.Contains(output, " 9\tmiss\thit\t\thit\thit\tmay\n")
|
||||
s.Contains(output, "The policy 'bypass' from rule #1 will be applied to this request.")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://admin.example.com", "--method=HEAD", "--username=tom", "--groups=basic,test", "--ip=192.168.2.3", "--verbose", "--config", "/config/configuration.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://admin.example.com", "--method=HEAD", "--username=tom", "--groups=basic,test", "--ip=192.168.2.3", "--verbose", "--config=/config/configuration.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
// This is an example of `authelia access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://admin.example.com --method=HEAD --username=tom --groups=basic,test --ip=192.168.2.3 --verbose`.
|
||||
|
@ -418,7 +480,7 @@ func (s *CLISuite) TestACLPolicyCheckVerbose() {
|
|||
s.Contains(output, " 9\tmiss\thit\t\thit\thit\tmiss\n")
|
||||
s.Contains(output, "The policy 'two_factor' from rule #2 will be applied to this request.")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://resources.example.com/resources/test", "--method=POST", "--username=john", "--groups=admin,test", "--ip=192.168.1.3", "--verbose", "--config", "/config/configuration.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://resources.example.com/resources/test", "--method=POST", "--username=john", "--groups=admin,test", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
// This is an example of `authelia access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://resources.example.com/resources/test --method=POST --username=john --groups=admin,test --ip=192.168.1.3 --verbose`.
|
||||
|
@ -435,7 +497,7 @@ func (s *CLISuite) TestACLPolicyCheckVerbose() {
|
|||
s.Contains(output, " 9\tmiss\thit\t\thit\thit\thit\n")
|
||||
s.Contains(output, "The policy 'one_factor' from rule #5 will be applied to this request.")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://user.example.com/resources/test", "--method=HEAD", "--username=john", "--groups=admin,test", "--ip=192.168.1.3", "--verbose", "--config", "/config/configuration.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://user.example.com/resources/test", "--method=HEAD", "--username=john", "--groups=admin,test", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
// This is an example of `access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://user.example.com --method=HEAD --username=john --groups=admin,test --ip=192.168.1.3 --verbose`.
|
||||
|
@ -452,7 +514,7 @@ func (s *CLISuite) TestACLPolicyCheckVerbose() {
|
|||
s.Contains(output, "* 9\thit\thit\t\thit\thit\thit\n")
|
||||
s.Contains(output, "The policy 'one_factor' from rule #9 will be applied to this request.")
|
||||
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://user.example.com", "--method=HEAD", "--ip=192.168.1.3", "--verbose", "--config", "/config/configuration.yml"})
|
||||
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://user.example.com", "--method=HEAD", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
|
||||
s.Assert().NoError(err)
|
||||
|
||||
// This is an example of `authelia access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://user.example.com --method=HEAD --ip=192.168.1.3 --verbose`.
|
||||
|
|
Loading…
Reference in New Issue
Block a user