2021-01-16 17:25:02 +07:00
package suites
import (
2022-06-27 15:27:57 +07:00
"bytes"
2021-11-25 08:56:58 +07:00
"context"
"fmt"
2021-01-16 17:25:02 +07:00
"os"
2021-06-18 11:35:43 +07:00
"regexp"
2021-12-01 19:11:29 +07:00
"strconv"
2021-01-16 17:25:02 +07:00
"testing"
"github.com/stretchr/testify/suite"
2022-04-09 14:13:19 +07:00
"gopkg.in/yaml.v3"
2021-11-25 08:56:58 +07:00
2022-03-06 12:47:40 +07:00
"github.com/authelia/authelia/v4/internal/model"
2021-11-25 08:56:58 +07:00
"github.com/authelia/authelia/v4/internal/storage"
2022-06-27 15:27:57 +07:00
"github.com/authelia/authelia/v4/internal/utils"
2021-01-16 17:25:02 +07:00
)
type CLISuite struct {
* CommandSuite
}
func NewCLISuite ( ) * CLISuite {
return & CLISuite { CommandSuite : new ( CommandSuite ) }
}
func ( s * CLISuite ) SetupSuite ( ) {
dockerEnvironment := NewDockerEnvironment ( [ ] string {
"internal/suites/docker-compose.yml" ,
"internal/suites/CLI/docker-compose.yml" ,
"internal/suites/example/compose/authelia/docker-compose.backend.{}.yml" ,
} )
s . DockerEnvironment = dockerEnvironment
}
func ( s * CLISuite ) SetupTest ( ) {
testArg := ""
coverageArg := ""
2021-12-01 10:32:58 +07:00
if os . Getenv ( "CI" ) == t {
2022-06-27 15:27:57 +07:00
testArg = "-test.coverprofile=/authelia/coverage-$(cat /proc/sys/kernel/random/uuid).txt"
2021-01-16 17:25:02 +07:00
coverageArg = "COVERAGE"
}
s . testArg = testArg
s . coverageArg = coverageArg
}
2021-06-18 11:35:43 +07:00
func ( s * CLISuite ) TestShouldPrintBuildInformation ( ) {
2022-04-05 06:57:47 +07:00
if os . Getenv ( "CI" ) == "false" {
s . T ( ) . Skip ( "Skipping testing in dev environment" )
}
2021-08-03 16:55:21 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "build-info" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2021-06-18 11:35:43 +07:00
s . Assert ( ) . Contains ( output , "Last Tag: " )
s . Assert ( ) . Contains ( output , "State: " )
s . Assert ( ) . Contains ( output , "Branch: " )
s . Assert ( ) . Contains ( output , "Build Number: " )
s . Assert ( ) . Contains ( output , "Build OS: " )
s . Assert ( ) . Contains ( output , "Build Arch: " )
s . Assert ( ) . Contains ( output , "Build Date: " )
r := regexp . MustCompile ( ` ^Last Tag: v\d+\.\d+\.\d+\nState: (tagged|untagged) (clean|dirty)\nBranch: [^\s\n]+\nCommit: [0-9a-f] { 40}\nBuild Number: \d+\nBuild OS: (linux|darwin|windows|freebsd)\nBuild Arch: (amd64|arm|arm64)\nBuild Date: (Sun|Mon|Tue|Wed|Thu|Fri|Sat), \d { 2} (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d { 4} \d { 2}:\d { 2}:\d { 2} [+-]\d { 4}\nExtra: \n ` )
s . Assert ( ) . Regexp ( r , output )
}
2021-01-17 06:23:35 +07:00
func ( s * CLISuite ) TestShouldPrintVersion ( ) {
2021-06-18 11:35:43 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "--version" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2021-06-18 11:35:43 +07:00
s . Assert ( ) . Contains ( output , "authelia version" )
2021-01-17 06:23:35 +07:00
}
2021-01-16 17:25:02 +07:00
func ( s * CLISuite ) TestShouldValidateConfig ( ) {
2022-03-02 14:50:36 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "validate-config" , "--config=/config/configuration.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-02-28 10:15:01 +07:00
s . Assert ( ) . Contains ( output , "Configuration parsed and loaded successfully without errors." )
2021-01-16 17:25:02 +07:00
}
func ( s * CLISuite ) TestShouldFailValidateConfig ( ) {
2022-03-02 14:50:36 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "validate-config" , "--config=/config/invalid.yml" } )
2022-02-28 10:15:01 +07:00
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" )
2021-01-16 17:25:02 +07:00
}
func ( s * CLISuite ) TestShouldHashPasswordArgon2id ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "hash-password" , "test" , "-m" , "32" , "-s" , "test1234" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-02 06:18:45 +07:00
s . Assert ( ) . Contains ( output , "Password hash: $argon2id$v=19$m=32768,t=3,p=4$" )
2021-01-16 17:25:02 +07:00
}
func ( s * CLISuite ) TestShouldHashPasswordSHA512 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "hash-password" , "test" , "-z" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2021-01-16 17:25:02 +07:00
s . Assert ( ) . Contains ( output , "Password hash: $6$rounds=50000" )
}
2022-06-27 15:27:57 +07:00
func ( s * CLISuite ) TestShouldGenerateRSACertificateRequest ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "request" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate Request" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tSignature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate Request: /tmp/request.csr" )
}
func ( s * CLISuite ) TestShouldGenerateECDSACurveP224CertificateRequest ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "request" , "--curve=P224" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate Request" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tSignature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-224" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate Request: /tmp/request.csr" )
}
func ( s * CLISuite ) TestShouldGenerateECDSACurveP256CertificateRequest ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "request" , "--curve=P256" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate Request" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tSignature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-256" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate Request: /tmp/request.csr" )
}
func ( s * CLISuite ) TestShouldGenerateECDSACurveP384CertificateRequest ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "request" , "--curve=P384" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate Request" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tSignature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-384" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate Request: /tmp/request.csr" )
}
func ( s * CLISuite ) TestShouldGenerateECDSACurveP521CertificateRequest ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "request" , "--curve=P521" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate Request" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tSignature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-521" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate Request: /tmp/request.csr" )
}
func ( s * CLISuite ) TestShouldGenerateEd25519CertificateRequest ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ed25519" , "request" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate Request" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tSignature Algorithm: Ed25519, Public Key Algorithm: Ed25519" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate Request: /tmp/request.csr" )
}
2021-01-16 17:25:02 +07:00
func ( s * CLISuite ) TestShouldGenerateCertificateRSA ( ) {
2022-06-27 15:27:57 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
2021-01-16 17:25:02 +07:00
}
func ( s * CLISuite ) TestShouldGenerateCertificateRSAWithIPAddress ( ) {
2022-06-27 15:27:57 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name=example.com" , "--sans" , "*.example.com,127.0.0.1" , "--directory=/tmp/" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com, IP.1:127.0.0.1" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
2021-01-16 17:25:02 +07:00
}
2022-06-27 15:27:57 +07:00
func ( s * CLISuite ) TestShouldGenerateCertificateRSAWithNotBefore ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name=example.com" , "--sans='*.example.com'" , "--not-before" , "'Jan 1 15:04:05 2011'" , "--directory=/tmp/" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tNot Before: 2011-01-01T15:04:05Z, Not After: 2012-01-01T15:04:05Z" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
2021-01-16 17:25:02 +07:00
}
2022-06-27 15:27:57 +07:00
func ( s * CLISuite ) TestShouldFailGenerateCertificateRSAWithInvalidNotBefore ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name=example.com" , "--sans='*.example.com'" , "--not-before" , "Jan" , "--directory=/tmp/" } )
2021-01-16 17:25:02 +07:00
s . Assert ( ) . NotNil ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Error: failed to parse not before: parsing time \"Jan\" as \"Jan 2 15:04:05 2006\": cannot parse \"\" as \"2\"" )
}
func ( s * CLISuite ) TestShouldGenerateCertificateRSAWith4096Bits ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--bits=4096" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 4096" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
}
func ( s * CLISuite ) TestShouldGenerateCertificateWithCustomizedSubject ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name=example.com" , "--sans='*.example.com'" , "--country=Australia" , "--organization='Acme Co.'" , "--organizational-unit=Tech" , "--province=QLD" , "--street-address='123 Smith St'" , "--postcode=4000" , "--locality=Internet" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Acme Co.], Organizational Unit: [Tech]" )
s . Assert ( ) . Contains ( output , "\tCountry: [Australia], Province: [QLD], Street Address: [123 Smith St], Postal Code: [4000], Locality: [Internet]" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
2021-01-16 17:25:02 +07:00
}
func ( s * CLISuite ) TestShouldGenerateCertificateCA ( ) {
2022-06-27 15:27:57 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name='Authelia Standalone Root Certificate Authority'" , "--ca" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: Authelia Standalone Root Certificate Authority, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: true, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: " )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/ca.private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/ca.public.crt" )
}
func ( s * CLISuite ) TestShouldGenerateCertificateCAAndSignCertificate ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name='Authelia Standalone Root Certificate Authority'" , "--ca" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: Authelia Standalone Root Certificate Authority, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: true, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: " )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/ca.private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/ca.public.crt" )
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name=example.com" , "--sans='*.example.com'" , "--path.ca" , "/tmp/" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tAuthelia Standalone Root Certificate Authority" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , ", Expires: " )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
// Check the certificates look fine.
privateKeyData , err := os . ReadFile ( "/tmp/private.pem" )
s . Assert ( ) . NoError ( err )
certificateData , err := os . ReadFile ( "/tmp/public.crt" )
s . Assert ( ) . NoError ( err )
privateKeyCAData , err := os . ReadFile ( "/tmp/ca.private.pem" )
s . Assert ( ) . NoError ( err )
certificateCAData , err := os . ReadFile ( "/tmp/ca.public.crt" )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . False ( bytes . Equal ( privateKeyData , privateKeyCAData ) )
s . Assert ( ) . False ( bytes . Equal ( certificateData , certificateCAData ) )
privateKey , err := utils . ParseX509FromPEM ( privateKeyData )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . True ( utils . IsX509PrivateKey ( privateKey ) )
privateCAKey , err := utils . ParseX509FromPEM ( privateKeyCAData )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . True ( utils . IsX509PrivateKey ( privateCAKey ) )
c , err := utils . ParseX509FromPEM ( certificateData )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . False ( utils . IsX509PrivateKey ( c ) )
cCA , err := utils . ParseX509FromPEM ( certificateCAData )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . False ( utils . IsX509PrivateKey ( cCA ) )
certificate , ok := utils . CastX509AsCertificate ( c )
s . Assert ( ) . True ( ok )
certificateCA , ok := utils . CastX509AsCertificate ( cCA )
s . Assert ( ) . True ( ok )
s . Require ( ) . NotNil ( certificate )
s . Require ( ) . NotNil ( certificateCA )
err = certificate . CheckSignatureFrom ( certificateCA )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2021-01-16 17:25:02 +07:00
}
func ( s * CLISuite ) TestShouldGenerateCertificateEd25519 ( ) {
2022-06-27 15:27:57 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ed25519" , "generate" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: Ed25519, Public Key Algorithm: Ed25519" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
}
func ( s * CLISuite ) TestShouldFailGenerateCertificateParseNotBefore ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "generate" , "--not-before=invalid" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NotNil ( err )
s . Assert ( ) . Contains ( output , "Error: failed to parse not before: parsing time \"invalid\" as \"Jan 2 15:04:05 2006\": cannot parse \"invalid\" as \"Jan\"" )
2021-01-16 17:25:02 +07:00
}
func ( s * CLISuite ) TestShouldFailGenerateCertificateECDSA ( ) {
2022-06-27 15:27:57 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "generate" , "--curve=invalid" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
2021-01-16 17:25:02 +07:00
s . Assert ( ) . NotNil ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Error: invalid curve 'invalid' was specified: curve must be P224, P256, P384, or P521" )
}
func ( s * CLISuite ) TestShouldGenerateCertificateECDSACurveP224 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "generate" , "--curve=P224" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-224" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
}
func ( s * CLISuite ) TestShouldGenerateCertificateECDSACurveP256 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "generate" , "--curve=P256" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-256" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
}
func ( s * CLISuite ) TestShouldGenerateCertificateECDSACurveP384 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "generate" , "--curve=P384" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-384" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
}
func ( s * CLISuite ) TestShouldGenerateCertificateECDSACurveP521 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "ecdsa" , "generate" , "--curve=P521" , "--common-name=example.com" , "--sans='*.example.com'" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating Certificate" )
s . Assert ( ) . Contains ( output , "\tSerial: " )
s . Assert ( ) . Contains ( output , "Signed By:\n\tSelf-Signed" )
s . Assert ( ) . Contains ( output , "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []" )
s . Assert ( ) . Contains ( output , "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []" )
s . Assert ( ) . Contains ( output , "\tCA: false, CSR: false, Signature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-521" )
s . Assert ( ) . Contains ( output , "\tSubject Alternative Names: DNS.1:*.example.com" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tCertificate: /tmp/public.crt" )
}
func ( s * CLISuite ) TestShouldGenerateRSAKeyPair ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "rsa" , "generate" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating key pair" )
s . Assert ( ) . Contains ( output , "Algorithm: RSA-256 2048 bits\n\n" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tPublic Key: /tmp/public.pem" )
}
func ( s * CLISuite ) TestShouldGenerateRSAKeyPairWith4069Bits ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "rsa" , "generate" , "--bits=4096" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating key pair" )
s . Assert ( ) . Contains ( output , "Algorithm: RSA-512 4096 bits\n\n" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tPublic Key: /tmp/public.pem" )
}
func ( s * CLISuite ) TestShouldGenerateECDSAKeyPair ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "ecdsa" , "generate" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating key pair" )
s . Assert ( ) . Contains ( output , "Algorithm: ECDSA Curve P-256\n\n" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tPublic Key: /tmp/public.pem" )
}
func ( s * CLISuite ) TestShouldGenerateECDSAKeyPairCurveP224 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "ecdsa" , "generate" , "--curve=P224" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Generating key pair" )
s . Assert ( ) . Contains ( output , "Algorithm: ECDSA Curve P-224\n\n" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tPublic Key: /tmp/public.pem" )
2021-01-16 17:25:02 +07:00
}
2022-06-27 15:27:57 +07:00
func ( s * CLISuite ) TestShouldGenerateECDSAKeyPairCurveP256 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "ecdsa" , "generate" , "--curve=P256" , "--directory=/tmp/" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Generating key pair" )
s . Assert ( ) . Contains ( output , "Algorithm: ECDSA Curve P-256\n\n" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tPublic Key: /tmp/public.pem" )
2021-01-16 17:25:02 +07:00
}
2022-06-27 15:27:57 +07:00
func ( s * CLISuite ) TestShouldGenerateECDSAKeyPairCurveP384 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "ecdsa" , "generate" , "--curve=P384" , "--directory=/tmp/" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Generating key pair" )
s . Assert ( ) . Contains ( output , "Algorithm: ECDSA Curve P-384\n\n" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tPublic Key: /tmp/public.pem" )
2021-01-16 17:25:02 +07:00
}
2022-06-27 15:27:57 +07:00
func ( s * CLISuite ) TestShouldGenerateECDSAKeyPairCurveP521 ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "ecdsa" , "generate" , "--curve=P521" , "--directory=/tmp/" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Generating key pair" )
s . Assert ( ) . Contains ( output , "Algorithm: ECDSA Curve P-521\n\n" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tPublic Key: /tmp/public.pem" )
2021-01-16 17:25:02 +07:00
}
2022-06-27 15:27:57 +07:00
func ( s * CLISuite ) TestShouldGenerateEd25519KeyPair ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "ed25519" , "generate" , "--directory=/tmp/" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-06-27 15:27:57 +07:00
s . Assert ( ) . Contains ( output , "Generating key pair" )
s . Assert ( ) . Contains ( output , "Algorithm: Ed25519\n\n" )
s . Assert ( ) . Contains ( output , "Output Paths:" )
s . Assert ( ) . Contains ( output , "\tPrivate Key: /tmp/private.pem" )
s . Assert ( ) . Contains ( output , "\tPublic Key: /tmp/public.pem" )
}
func ( s * CLISuite ) TestShouldNotGenerateECDSAKeyPairCurveInvalid ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "pair" , "ecdsa" , "generate" , "--curve=invalid" , "--directory=/tmp/" } )
s . Assert ( ) . NotNil ( err )
s . Assert ( ) . Contains ( output , "Error: invalid curve 'invalid' was specified: curve must be P224, P256, P384, or P521" )
}
func ( s * CLISuite ) TestShouldNotGenerateRSAWithBadCAPath ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--path.ca=/tmp/invalid" , "--directory=/tmp/" } )
s . Assert ( ) . NotNil ( err )
s . Assert ( ) . Contains ( output , "Error: could not read private key file '/tmp/invalid/ca.private.pem': open /tmp/invalid/ca.private.pem: no such file or directory\n" )
}
func ( s * CLISuite ) TestShouldNotGenerateRSAWithBadCAFileNames ( ) {
var (
err error
output string
)
_ , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name='Authelia Standalone Root Certificate Authority'" , "--ca" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--path.ca=/tmp/" , "--file.ca-private-key=invalid.pem" , "--directory=/tmp/" } )
s . Assert ( ) . NotNil ( err )
s . Assert ( ) . Contains ( output , "Error: could not read private key file '/tmp/invalid.pem': open /tmp/invalid.pem: no such file or directory\n" )
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--path.ca=/tmp/" , "--file.ca-certificate=invalid.crt" , "--directory=/tmp/" } )
s . Assert ( ) . NotNil ( err )
s . Assert ( ) . Contains ( output , "Error: could not read certificate file '/tmp/invalid.crt': open /tmp/invalid.crt: no such file or directory\n" )
}
func ( s * CLISuite ) TestShouldNotGenerateRSAWithBadCAFileContent ( ) {
var (
err error
output string
)
_ , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--common-name='Authelia Standalone Root Certificate Authority'" , "--ca" , "--directory=/tmp/" } )
s . Assert ( ) . NoError ( err )
s . Require ( ) . NoError ( os . WriteFile ( "/tmp/ca.private.bad.pem" , [ ] byte ( "INVALID" ) , 0600 ) ) //nolint:gosec
s . Require ( ) . NoError ( os . WriteFile ( "/tmp/ca.public.bad.crt" , [ ] byte ( "INVALID" ) , 0600 ) ) //nolint:gosec
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--path.ca=/tmp/" , "--file.ca-private-key=ca.private.bad.pem" , "--directory=/tmp/" } )
s . Assert ( ) . NotNil ( err )
s . Assert ( ) . Contains ( output , "Error: could not parse private key from file '/tmp/ca.private.bad.pem': failed to parse PEM block containing the key\n" )
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "crypto" , "certificate" , "rsa" , "generate" , "--path.ca=/tmp/" , "--file.ca-certificate=ca.public.bad.crt" , "--directory=/tmp/" } )
s . Assert ( ) . NotNil ( err )
s . Assert ( ) . Contains ( output , "Error: could not parse certificate from file '/tmp/ca.public.bad.crt': failed to parse PEM block containing the key\n" )
2021-01-16 17:25:02 +07:00
}
2021-11-25 08:56:58 +07:00
func ( s * CLISuite ) TestStorageShouldShowErrWithoutConfig ( ) {
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "schema-info" } )
s . Assert ( ) . EqualError ( err , "exit status 1" )
2022-06-28 14:13:47 +07:00
s . Assert ( ) . Contains ( output , "Error: storage: configuration for a 'local', 'mysql' or 'postgres' database must be provided, storage: option 'encryption_key' is required\n" )
2021-11-25 08:56:58 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "history" } )
s . Assert ( ) . EqualError ( err , "exit status 1" )
2022-06-28 14:13:47 +07:00
s . Assert ( ) . Contains ( output , "Error: storage: configuration for a 'local', 'mysql' or 'postgres' database must be provided, storage: option 'encryption_key' is required\n" )
2021-11-25 08:56:58 +07:00
}
func ( s * CLISuite ) TestStorage00ShouldShowCorrectPreInitInformation ( ) {
2021-12-01 19:11:29 +07:00
_ = os . Remove ( "/tmp/db.sqlite3" )
2022-03-02 14:50:36 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "schema-info" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
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\) ` )
s . Assert ( ) . Regexp ( pattern , output )
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 ` )
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "totp" , "export" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Regexp ( patternOutdated , output )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "encryption" , "change-key" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Regexp ( patternOutdated , output )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "encryption" , "check" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Could not check encryption key for validity. The schema version doesn't support encryption." )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "down" , "--target=0" , "--destroy-data" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: schema migration target version 0 is the same current version 0" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "up" , "--target=2147483640" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
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" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "history" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "No migration history is available for schemas that not version 1 or above.\n" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "list-up" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Storage Schema Migration List (Up)\n\nVersion\t\tDescription\n1\t\tInitial Schema\n" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "list-down" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Storage Schema Migration List (Down)\n\nNo Migrations Available\n" )
}
func ( s * CLISuite ) TestStorage01ShouldMigrateUp ( ) {
2022-03-02 14:50:36 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "up" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Require ( ) . NoError ( err )
pattern0 := regexp . MustCompile ( ` "Storage schema migration from \d+ to \d+ is being attempted" ` )
pattern1 := regexp . MustCompile ( ` "Storage schema migration from \d+ to \d+ is complete" ` )
s . Regexp ( pattern0 , output )
s . Regexp ( pattern1 , output )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "up" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: schema already up to date\n" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "history" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
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" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "list-up" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Storage Schema Migration List (Up)\n\nNo Migrations Available" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "list-down" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Storage Schema Migration List (Down)\n\nVersion\t\tDescription\n" )
s . Assert ( ) . Contains ( output , "1\t\tInitial Schema" )
}
func ( s * CLISuite ) TestStorage02ShouldShowSchemaInfo ( ) {
2022-03-02 14:50:36 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "schema-info" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-03-03 18:20:43 +07:00
s . Assert ( ) . Contains ( output , "Schema Version: " )
s . Assert ( ) . Contains ( output , "authentication_logs" )
s . Assert ( ) . Contains ( output , "identity_verification" )
s . Assert ( ) . Contains ( output , "duo_devices" )
s . Assert ( ) . Contains ( output , "user_preferences" )
s . Assert ( ) . Contains ( output , "migrations" )
s . Assert ( ) . Contains ( output , "encryption" )
s . Assert ( ) . Contains ( output , "encryption" )
s . Assert ( ) . Contains ( output , "webauthn_devices" )
s . Assert ( ) . Contains ( output , "totp_configurations" )
s . Assert ( ) . Contains ( output , "Schema Encryption Key: valid" )
2021-11-25 08:56:58 +07:00
}
func ( s * CLISuite ) TestStorage03ShouldExportTOTP ( ) {
2021-12-01 19:11:29 +07:00
storageProvider := storage . NewSQLiteProvider ( & storageLocalTmpConfig )
2021-11-25 08:56:58 +07:00
ctx := context . Background ( )
var (
2021-12-01 19:11:29 +07:00
err error
2021-11-25 08:56:58 +07:00
)
var (
expectedLines = make ( [ ] string , 0 , 3 )
expectedLinesCSV = make ( [ ] string , 0 , 4 )
output string
)
expectedLinesCSV = append ( expectedLinesCSV , "issuer,username,algorithm,digits,period,secret" )
2022-03-02 14:50:36 +07:00
testCases := [ ] struct {
2022-03-06 12:47:40 +07:00
config model . TOTPConfiguration
2022-03-02 14:50:36 +07:00
png bool
} {
2021-12-01 19:11:29 +07:00
{
2022-03-06 12:47:40 +07:00
config : model . TOTPConfiguration {
2022-03-02 14:50:36 +07:00
Username : "john" ,
Period : 30 ,
Digits : 6 ,
Algorithm : "SHA1" ,
} ,
2021-12-01 19:11:29 +07:00
} ,
{
2022-03-06 12:47:40 +07:00
config : model . TOTPConfiguration {
2022-03-02 14:50:36 +07:00
Username : "mary" ,
Period : 45 ,
Digits : 6 ,
Algorithm : "SHA1" ,
} ,
2021-12-01 19:11:29 +07:00
} ,
{
2022-03-06 12:47:40 +07:00
config : model . TOTPConfiguration {
2022-03-02 14:50:36 +07:00
Username : "fred" ,
Period : 30 ,
Digits : 8 ,
Algorithm : "SHA1" ,
} ,
2021-12-01 19:11:29 +07:00
} ,
{
2022-03-06 12:47:40 +07:00
config : model . TOTPConfiguration {
2022-03-02 14:50:36 +07:00
Username : "jone" ,
Period : 30 ,
Digits : 6 ,
Algorithm : "SHA512" ,
} ,
png : true ,
2021-12-01 19:11:29 +07:00
} ,
}
2021-11-25 08:56:58 +07:00
2022-03-02 14:50:36 +07:00
var (
2022-03-06 12:47:40 +07:00
config * model . TOTPConfiguration
2022-03-02 14:50:36 +07:00
fileInfo os . FileInfo
)
2021-11-25 08:56:58 +07:00
2022-03-02 14:50:36 +07:00
for _ , testCase := range testCases {
if testCase . png {
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "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" } )
2022-03-02 14:50:36 +07:00
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 {
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "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" } )
2022-03-02 14:50:36 +07:00
s . Assert ( ) . NoError ( err )
}
config , err = storageProvider . LoadTOTPConfiguration ( ctx , testCase . config . Username )
2021-12-01 19:11:29 +07:00
s . Assert ( ) . NoError ( err )
2022-03-02 14:50:36 +07:00
2021-12-01 19:11:29 +07:00
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 ( ) )
2021-11-25 08:56:58 +07:00
}
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "totp" , "export" , "--format=uri" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
for _ , expectedLine := range expectedLines {
s . Assert ( ) . Contains ( output , expectedLine )
}
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "totp" , "export" , "--format=csv" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
for _ , expectedLine := range expectedLinesCSV {
s . Assert ( ) . Contains ( output , expectedLine )
}
2022-03-02 14:50:36 +07:00
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "totp" , "export" , "--format=wrong" , "--config=/config/configuration.storage.yml" } )
2022-03-02 14:50:36 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: format must be csv, uri, or png" )
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "totp" , "export" , "--format=png" , "--dir=/tmp/qr" , "--config=/config/configuration.storage.yml" } )
2022-03-02 14:50:36 +07:00
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 ) )
}
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "totp" , "generate" , "test" , "--period=30" , "--algorithm=SHA1" , "--digits=6" , "--path=/tmp/qr.png" , "--config=/config/configuration.storage.yml" } )
2022-03-02 14:50:36 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: image output filepath already exists" )
2021-11-25 08:56:58 +07:00
}
2022-04-09 14:13:19 +07:00
func ( s * CLISuite ) TestStorage04ShouldManageUniqueID ( ) {
_ = os . Mkdir ( "/tmp/out" , 0777 )
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "export" , "--file=out.yml" , "--config=/config/configuration.storage.yml" } )
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: no data to export" )
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "add" , "john" , "--service=webauthn" , "--sector=''" , "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285" , "--config=/config/configuration.storage.yml" } )
s . Assert ( ) . EqualError ( err , "exit status 1" )
2022-04-25 15:49:18 +07:00
s . Assert ( ) . Contains ( output , "Error: the service name 'webauthn' is invalid, the valid values are: 'openid'" )
2022-04-09 14:13:19 +07:00
2022-04-25 15:49:18 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "add" , "john" , "--service=openid" , "--sector=''" , "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285" , "--config=/config/configuration.storage.yml" } )
2022-04-09 14:13:19 +07:00
s . Assert ( ) . NoError ( err )
2022-04-25 15:49:18 +07:00
s . Assert ( ) . Contains ( output , "Added User Opaque Identifier:\n\tService: openid\n\tSector: \n\tUsername: john\n\tIdentifier: 1097c8f8-83f2-4506-8138-5f40e83a1285\n\n" )
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "export" , "--file=/a/no/path/fileout.yml" , "--config=/config/configuration.storage.yml" } )
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: error occurred writing to file '/a/no/path/fileout.yml': open /a/no/path/fileout.yml: no such file or directory" )
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "export" , "--file=out.yml" , "--config=/config/configuration.storage.yml" } )
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: error occurred writing to file 'out.yml': open out.yml: permission denied" )
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "export" , "--file=/tmp/out/1.yml" , "--config=/config/configuration.storage.yml" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Exported 1 User Opaque Identifiers to /tmp/out/1.yml" )
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "export" , "--file=/tmp/out/1.yml" , "--config=/config/configuration.storage.yml" } )
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: must specify a file that doesn't exist but '/tmp/out/1.yml' exists" )
2022-04-25 15:49:18 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "add" , "john" , "--service=openid" , "--sector=''" , "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285" , "--config=/config/configuration.storage.yml" } )
2022-04-09 14:13:19 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: error inserting user opaque id for user 'john' with opaque id '1097c8f8-83f2-4506-8138-5f40e83a1285':" )
2022-04-25 15:49:18 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "add" , "john" , "--service=openid" , "--sector=''" , "--config=/config/configuration.storage.yml" } )
2022-04-09 14:13:19 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: error inserting user opaque id for user 'john' with opaque id" )
2022-04-25 15:49:18 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "add" , "john" , "--service=openid" , "--sector='openidconnect.com'" , "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285" , "--config=/config/configuration.storage.yml" } )
2022-04-09 14:13:19 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: error inserting user opaque id for user 'john' with opaque id '1097c8f8-83f2-4506-8138-5f40e83a1285':" )
2022-04-25 15:49:18 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "add" , "john" , "--service=openid" , "--sector='openidconnect.net'" , "--identifier=b0e17f48-933c-4cba-8509-ee9bfadf8ce5" , "--config=/config/configuration.storage.yml" } )
2022-04-09 14:13:19 +07:00
s . Assert ( ) . NoError ( err )
2022-04-25 15:49:18 +07:00
s . Assert ( ) . Contains ( output , "Added User Opaque Identifier:\n\tService: openid\n\tSector: openidconnect.net\n\tUsername: john\n\tIdentifier: b0e17f48-933c-4cba-8509-ee9bfadf8ce5\n\n" )
2022-04-09 14:13:19 +07:00
2022-04-25 15:49:18 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "add" , "john" , "--service=openid" , "--sector='bad-uuid.com'" , "--identifier=d49564dc-b7a1-11ec-8429-fcaa147128ea" , "--config=/config/configuration.storage.yml" } )
2022-04-09 14:13:19 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: the identifier providerd 'd49564dc-b7a1-11ec-8429-fcaa147128ea' is a version 1 UUID but only version 4 UUID's accepted as identifiers" )
2022-04-25 15:49:18 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "add" , "john" , "--service=openid" , "--sector='bad-uuid.com'" , "--identifier=asdmklasdm" , "--config=/config/configuration.storage.yml" } )
2022-04-09 14:13:19 +07:00
s . Assert ( ) . EqualError ( err , "exit status 1" )
s . Assert ( ) . Contains ( output , "Error: the identifier provided 'asdmklasdm' is invalid as it must be a version 4 UUID but parsing it had an error: invalid UUID length: 10" )
data , err := os . ReadFile ( "/tmp/out/1.yml" )
s . Assert ( ) . NoError ( err )
var export model . UserOpaqueIdentifiersExport
s . Assert ( ) . NoError ( yaml . Unmarshal ( data , & export ) )
s . Require ( ) . Len ( export . Identifiers , 1 )
s . Assert ( ) . Equal ( 1 , export . Identifiers [ 0 ] . ID )
s . Assert ( ) . Equal ( "1097c8f8-83f2-4506-8138-5f40e83a1285" , export . Identifiers [ 0 ] . Identifier . String ( ) )
s . Assert ( ) . Equal ( "john" , export . Identifiers [ 0 ] . Username )
s . Assert ( ) . Equal ( "" , export . Identifiers [ 0 ] . SectorID )
2022-04-25 15:49:18 +07:00
s . Assert ( ) . Equal ( "openid" , export . Identifiers [ 0 ] . Service )
2022-04-09 14:13:19 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "user" , "identifiers" , "export" , "--file=/tmp/out/2.yml" , "--config=/config/configuration.storage.yml" } )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Exported 2 User Opaque Identifiers to /tmp/out/2.yml" )
export = model . UserOpaqueIdentifiersExport { }
data , err = os . ReadFile ( "/tmp/out/2.yml" )
s . Assert ( ) . NoError ( err )
s . Assert ( ) . NoError ( yaml . Unmarshal ( data , & export ) )
s . Require ( ) . Len ( export . Identifiers , 2 )
s . Assert ( ) . Equal ( 1 , export . Identifiers [ 0 ] . ID )
s . Assert ( ) . Equal ( "1097c8f8-83f2-4506-8138-5f40e83a1285" , export . Identifiers [ 0 ] . Identifier . String ( ) )
s . Assert ( ) . Equal ( "john" , export . Identifiers [ 0 ] . Username )
s . Assert ( ) . Equal ( "" , export . Identifiers [ 0 ] . SectorID )
2022-04-25 15:49:18 +07:00
s . Assert ( ) . Equal ( "openid" , export . Identifiers [ 0 ] . Service )
2022-04-09 14:13:19 +07:00
s . Assert ( ) . Equal ( 2 , export . Identifiers [ 1 ] . ID )
s . Assert ( ) . Equal ( "b0e17f48-933c-4cba-8509-ee9bfadf8ce5" , export . Identifiers [ 1 ] . Identifier . String ( ) )
s . Assert ( ) . Equal ( "john" , export . Identifiers [ 1 ] . Username )
s . Assert ( ) . Equal ( "openidconnect.net" , export . Identifiers [ 1 ] . SectorID )
2022-04-25 15:49:18 +07:00
s . Assert ( ) . Equal ( "openid" , export . Identifiers [ 1 ] . Service )
2022-04-09 14:13:19 +07:00
}
func ( s * CLISuite ) TestStorage05ShouldChangeEncryptionKey ( ) {
2022-03-02 14:50:36 +07:00
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" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Completed the encryption key change. Please adjust your configuration to use the new key.\n" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "schema-info" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2022-03-03 18:20:43 +07:00
s . Assert ( ) . Contains ( output , "Schema Version: " )
s . Assert ( ) . Contains ( output , "authentication_logs" )
s . Assert ( ) . Contains ( output , "identity_verification" )
s . Assert ( ) . Contains ( output , "duo_devices" )
s . Assert ( ) . Contains ( output , "user_preferences" )
s . Assert ( ) . Contains ( output , "migrations" )
s . Assert ( ) . Contains ( output , "encryption" )
s . Assert ( ) . Contains ( output , "encryption" )
s . Assert ( ) . Contains ( output , "webauthn_devices" )
s . Assert ( ) . Contains ( output , "totp_configurations" )
s . Assert ( ) . Contains ( output , "Schema Encryption Key: invalid" )
2021-11-25 08:56:58 +07:00
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "encryption" , "check" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
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" )
2022-03-02 14:50:36 +07:00
output , err = s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "encryption" , "check" , "--verbose" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
2021-12-01 19:11:29 +07:00
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" )
2021-11-25 08:56:58 +07:00
2022-03-02 14:50:36 +07:00
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" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Encryption key validation: success.\n" )
2022-03-02 14:50:36 +07:00
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" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
s . Assert ( ) . Contains ( output , "Encryption key validation: success.\n" )
2022-03-02 14:50:36 +07:00
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" )
2021-11-25 08:56:58 +07:00
}
2022-04-09 14:13:19 +07:00
func ( s * CLISuite ) TestStorage06ShouldMigrateDown ( ) {
2022-03-02 14:50:36 +07:00
output , err := s . Exec ( "authelia-backend" , [ ] string { "authelia" , s . testArg , s . coverageArg , "storage" , "migrate" , "down" , "--target=0" , "--destroy-data" , "--config=/config/configuration.storage.yml" } )
2021-11-25 08:56:58 +07:00
s . Assert ( ) . NoError ( err )
pattern0 := regexp . MustCompile ( ` "Storage schema migration from \d+ to \d+ is being attempted" ` )
pattern1 := regexp . MustCompile ( ` "Storage schema migration from \d+ to \d+ is complete" ` )
s . Regexp ( pattern0 , output )
s . Regexp ( pattern1 , output )
}
2022-02-28 10:15:01 +07:00
func ( s * CLISuite ) TestACLPolicyCheckVerbose ( ) {
2022-03-02 14:50:36 +07:00
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" } )
2022-02-28 10:15:01 +07:00
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`.
s . Contains ( output , "Performing policy check for request to 'https://public.example.com' method 'GET'.\n\n" )
s . Contains ( output , " #\tDomain\tResource\tMethod\tNetwork\tSubject\n" )
s . Contains ( output , "* 1\thit\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 2\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 3\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 4\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 5\tmiss\tmiss\t\thit\thit\thit\n" )
s . Contains ( output , " 6\tmiss\thit\t\tmiss\thit\thit\n" )
s . Contains ( output , " 7\tmiss\thit\t\thit\tmiss\thit\n" )
s . Contains ( output , " 8\tmiss\thit\t\thit\thit\tmay\n" )
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." )
2022-03-02 14:50:36 +07:00
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" } )
2022-02-28 10:15:01 +07:00
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`.
s . Contains ( output , "Performing policy check for request to 'https://admin.example.com' method 'HEAD' username 'tom' groups 'basic,test' from IP '192.168.2.3'.\n\n" )
s . Contains ( output , " #\tDomain\tResource\tMethod\tNetwork\tSubject\n" )
s . Contains ( output , " #\tDomain\tResource\tMethod\tNetwork\tSubject\n" )
s . Contains ( output , " 1\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , "* 2\thit\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 3\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 4\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 5\tmiss\tmiss\t\thit\thit\thit\n" )
s . Contains ( output , " 6\tmiss\thit\t\tmiss\thit\thit\n" )
s . Contains ( output , " 7\tmiss\thit\t\thit\tmiss\thit\n" )
s . Contains ( output , " 8\tmiss\thit\t\thit\thit\thit\n" )
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." )
2022-03-02 14:50:36 +07:00
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" } )
2022-02-28 10:15:01 +07:00
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`.
s . Contains ( output , "Performing policy check for request to 'https://resources.example.com/resources/test' method 'POST' username 'john' groups 'admin,test' from IP '192.168.1.3'.\n\n" )
s . Contains ( output , " #\tDomain\tResource\tMethod\tNetwork\tSubject\n" )
s . Contains ( output , " 1\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 2\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 3\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 4\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , "* 5\thit\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 6\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 7\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 8\tmiss\thit\t\thit\thit\tmiss\n" )
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." )
2022-03-02 14:50:36 +07:00
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" } )
2022-02-28 10:15:01 +07:00
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`.
s . Contains ( output , "Performing policy check for request to 'https://user.example.com/resources/test' method 'HEAD' username 'john' groups 'admin,test' from IP '192.168.1.3'.\n\n" )
s . Contains ( output , " #\tDomain\tResource\tMethod\tNetwork\tSubject\n" )
s . Contains ( output , " 1\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 2\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 3\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 4\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 5\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 6\tmiss\thit\t\tmiss\thit\thit\n" )
s . Contains ( output , " 7\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 8\tmiss\thit\t\thit\thit\tmiss\n" )
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." )
2022-03-02 14:50:36 +07:00
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" } )
2022-02-28 10:15:01 +07:00
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`.
s . Contains ( output , "Performing policy check for request to 'https://user.example.com' method 'HEAD' from IP '192.168.1.3'.\n\n" )
s . Contains ( output , " #\tDomain\tResource\tMethod\tNetwork\tSubject\n" )
s . Contains ( output , " 1\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 2\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 3\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 4\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 5\tmiss\tmiss\t\thit\thit\thit\n" )
s . Contains ( output , " 6\tmiss\thit\t\tmiss\thit\thit\n" )
s . Contains ( output , " 7\tmiss\thit\t\thit\thit\thit\n" )
s . Contains ( output , " 8\tmiss\thit\t\thit\thit\tmay\n" )
s . Contains ( output , "~ 9\thit\thit\t\thit\thit\tmay\n" )
s . Contains ( output , "The policy 'one_factor' from rule #9 will potentially be applied to this request. Otherwise the policy 'bypass' from the default policy will be." )
}
2021-01-16 17:25:02 +07:00
func TestCLISuite ( t * testing . T ) {
2021-03-14 14:08:26 +07:00
if testing . Short ( ) {
t . Skip ( "skipping suite test in short mode" )
}
2021-01-16 17:25:02 +07:00
suite . Run ( t , NewCLISuite ( ) )
}