diff options
| author | James Elliott <james-d-elliott@users.noreply.github.com> | 2022-12-23 15:00:23 +1100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-12-23 15:00:23 +1100 | 
| commit | d7ab3bb6333af2c7bede8c10b99b216bbe215d07 (patch) | |
| tree | 1e30120a586f7f76a694a91d6f49ae5eca1e2078 | |
| parent | 0130edb870137b86ceb686505616796bd20c9b1a (diff) | |
feat(commands): storage import/export commands (#4545)
This adds commands to export and import TOTP configurations and Webauthn devices as YAML.
73 files changed, 1630 insertions, 541 deletions
diff --git a/docs/content/en/configuration/second-factor/time-based-one-time-password.md b/docs/content/en/configuration/second-factor/time-based-one-time-password.md index a7b64a3c6..0783aa149 100644 --- a/docs/content/en/configuration/second-factor/time-based-one-time-password.md +++ b/docs/content/en/configuration/second-factor/time-based-one-time-password.md @@ -169,23 +169,8 @@ This may be inconvenient for some users who wish to export TOTP keys from Authel  a command specifically for exporting TOTP configurations from the database. These commands require the configuration or  at least a minimal configuration that has the storage backend connection details and the encryption key. -Export in [Key URI Format](https://github.com/google/google-authenticator/wiki/Key-Uri-Format): - -```bash -authelia storage user totp export --format uri -``` - -Export as CSV: - -```bash -authelia storage user totp export --format csv -``` - -Help: - -```bash -authelia storage user totp export --help -``` +See the [CLI Documentation](../../reference/cli/authelia/authelia_storage_user_totp_export.md) for methods to perform +exports.  [RFC4226]: https://www.rfc-editor.org/rfc/rfc4226.html  [RFC6238]: https://www.rfc-editor.org/rfc/rfc6238.html diff --git a/docs/content/en/reference/cli/authelia/authelia.md b/docs/content/en/reference/cli/authelia/authelia.md index e4c81e9e3..c8df14ea8 100644 --- a/docs/content/en/reference/cli/authelia/authelia.md +++ b/docs/content/en/reference/cli/authelia/authelia.md @@ -42,8 +42,8 @@ authelia --config /etc/authelia/config/  ### Options  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'    -h, --help                                  help for authelia  ``` diff --git a/docs/content/en/reference/cli/authelia/authelia_access-control.md b/docs/content/en/reference/cli/authelia/authelia_access-control.md index 0755b06a5..c622e04e4 100644 --- a/docs/content/en/reference/cli/authelia/authelia_access-control.md +++ b/docs/content/en/reference/cli/authelia/authelia_access-control.md @@ -35,8 +35,8 @@ authelia access-control --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_access-control_check-policy.md b/docs/content/en/reference/cli/authelia/authelia_access-control_check-policy.md index 37de027c2..5ba1eec21 100644 --- a/docs/content/en/reference/cli/authelia/authelia_access-control_check-policy.md +++ b/docs/content/en/reference/cli/authelia/authelia_access-control_check-policy.md @@ -65,8 +65,8 @@ authelia access-control check-policy --config config.yml --url https://example.c  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_build-info.md b/docs/content/en/reference/cli/authelia/authelia_build-info.md index f08113650..0d1060ed8 100644 --- a/docs/content/en/reference/cli/authelia/authelia_build-info.md +++ b/docs/content/en/reference/cli/authelia/authelia_build-info.md @@ -48,8 +48,8 @@ authelia build-info  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto.md b/docs/content/en/reference/cli/authelia/authelia_crypto.md index 7f1ccc86e..a89a1fe6e 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto.md @@ -37,8 +37,8 @@ authelia crypto --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate.md index f275803fe..33ddd6d39 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate.md @@ -37,8 +37,8 @@ authelia crypto certificate --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa.md index 7be5c794a..8f244b1b9 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa.md @@ -37,8 +37,8 @@ authelia crypto certificate ecdsa --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md index e5215fa5e..13fc82481 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md @@ -62,8 +62,8 @@ authelia crypto certificate ecdsa generate --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md index cd813689c..271da38eb 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md @@ -57,8 +57,8 @@ authelia crypto certificate ecdsa request --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519.md index 1a7877fca..f3b6354a6 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519.md @@ -37,8 +37,8 @@ authelia crypto certificate ed25519 --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md index cd59da864..44e806357 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md @@ -61,8 +61,8 @@ authelia crypto certificate ed25519 request --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md index a609b4332..f0f3a5f8d 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md @@ -56,8 +56,8 @@ authelia crypto certificate ed25519 request --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa.md index 947ea4a10..4f38b2e80 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa.md @@ -37,8 +37,8 @@ authelia crypto certificate rsa --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md index a1df7967d..e00aaf877 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md @@ -62,8 +62,8 @@ authelia crypto certificate rsa generate --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md index b3dd7cfb8..544cbf553 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md @@ -57,8 +57,8 @@ authelia crypto certificate rsa request --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_hash.md b/docs/content/en/reference/cli/authelia/authelia_crypto_hash.md index 2d8d678a4..bb48ad3eb 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_hash.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_hash.md @@ -37,8 +37,8 @@ authelia crypto hash --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate.md index 85a907ac7..0b06ebfe1 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate.md @@ -49,8 +49,8 @@ authelia crypto hash generate --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_argon2.md b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_argon2.md index a25abbbb3..d6e1efa49 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_argon2.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_argon2.md @@ -48,8 +48,8 @@ authelia crypto hash generate argon2 --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --no-confirm                            skip the password confirmation prompt        --password string                       manually supply the password rather than using the terminal prompt        --random                                uses a randomly generated password diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_bcrypt.md b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_bcrypt.md index 39d1a73fa..d33a72c6c 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_bcrypt.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_bcrypt.md @@ -43,8 +43,8 @@ authelia crypto hash generate bcrypt --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --no-confirm                            skip the password confirmation prompt        --password string                       manually supply the password rather than using the terminal prompt        --random                                uses a randomly generated password diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_pbkdf2.md b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_pbkdf2.md index 4acd6f3af..708a47df1 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_pbkdf2.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_pbkdf2.md @@ -44,8 +44,8 @@ authelia crypto hash generate pbkdf2 --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --no-confirm                            skip the password confirmation prompt        --password string                       manually supply the password rather than using the terminal prompt        --random                                uses a randomly generated password diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_scrypt.md b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_scrypt.md index dbb874d4a..dd172260d 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_scrypt.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_scrypt.md @@ -46,8 +46,8 @@ authelia crypto hash generate scrypt --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --no-confirm                            skip the password confirmation prompt        --password string                       manually supply the password rather than using the terminal prompt        --random                                uses a randomly generated password diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_sha2crypt.md b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_sha2crypt.md index 567a9ec3c..e0cbd7412 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_sha2crypt.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_generate_sha2crypt.md @@ -44,8 +44,8 @@ authelia crypto hash generate sha2crypt --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --no-confirm                            skip the password confirmation prompt        --password string                       manually supply the password rather than using the terminal prompt        --random                                uses a randomly generated password diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_validate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_validate.md index 66fdfb104..16d53f8f8 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_hash_validate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_hash_validate.md @@ -43,8 +43,8 @@ authelia crypto hash validate '$5$rounds=500000$WFjMpdCQxIkbNl0k$M0qZaZoK8Gwdh8C  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_pair.md b/docs/content/en/reference/cli/authelia/authelia_crypto_pair.md index c906cb517..5d9d3c57a 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_pair.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair.md @@ -37,8 +37,8 @@ authelia crypto pair --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa.md b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa.md index 4300c395c..1a2a51194 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa.md @@ -41,8 +41,8 @@ authelia crypto pair ecdsa --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa_generate.md index 0e0703182..5051e957c 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa_generate.md @@ -46,8 +46,8 @@ authelia crypto pair ecdsa generate --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519.md b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519.md index 77070c5b0..2f930e3f7 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519.md @@ -41,8 +41,8 @@ authelia crypto pair ed25519 --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519_generate.md index f730e25c4..f8f193683 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519_generate.md @@ -45,8 +45,8 @@ authelia crypto pair ed25519 generate --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa.md b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa.md index 4a760de6e..a04fb46c4 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa.md @@ -41,8 +41,8 @@ authelia crypto pair rsa --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa_generate.md index bf4f530ef..cc13a85b9 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa_generate.md @@ -46,8 +46,8 @@ authelia crypto pair rsa generate --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_rand.md b/docs/content/en/reference/cli/authelia/authelia_crypto_rand.md index 5c5ff7b80..98331df88 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_rand.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_rand.md @@ -52,8 +52,8 @@ authelia crypto rand --characters 0123456789ABCDEF  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_storage.md b/docs/content/en/reference/cli/authelia/authelia_storage.md index d1cdc0b42..bb3281d5b 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage.md @@ -56,8 +56,8 @@ authelia storage --help  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md b/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md index 17905e448..062570360 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md @@ -37,8 +37,8 @@ authelia storage encryption --help  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_encryption_change-key.md b/docs/content/en/reference/cli/authelia/authelia_storage_encryption_change-key.md index 77a2c5393..6bfe33d7f 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_encryption_change-key.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_encryption_change-key.md @@ -43,8 +43,8 @@ authelia storage encryption change-key --encryption-key b3453fde-ecc2-4a1f-9422-  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_encryption_check.md b/docs/content/en/reference/cli/authelia/authelia_storage_encryption_check.md index 6d8368d05..b22d5b959 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_encryption_check.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_encryption_check.md @@ -45,8 +45,8 @@ authelia storage encryption check --verbose --encryption-key b3453fde-ecc2-4a1f-  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md index a80eaa8a0..d5f262cb6 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md @@ -37,8 +37,8 @@ authelia storage migrate --help  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_down.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_down.md index 5ef59efa3..bf1379897 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_down.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_down.md @@ -46,8 +46,8 @@ authelia storage migrate down --target 20 --encryption-key b3453fde-ecc2-4a1f-94  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_history.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_history.md index a3afa9f95..3762e80e0 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_history.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_history.md @@ -43,8 +43,8 @@ authelia storage migrate history --encryption-key b3453fde-ecc2-4a1f-9422-2707dd  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-down.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-down.md index 6ea42249e..c62a7e3e7 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-down.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-down.md @@ -44,8 +44,8 @@ authelia storage migrate list-down --encryption-key b3453fde-ecc2-4a1f-9422-2707  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-up.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-up.md index eacaf8129..187dbedf1 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-up.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_list-up.md @@ -44,8 +44,8 @@ authelia storage migrate list-up --encryption-key b3453fde-ecc2-4a1f-9422-2707dd  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_up.md b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_up.md index 576d8a31d..d84930536 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_migrate_up.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate_up.md @@ -46,8 +46,8 @@ authelia storage migrate up --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed49  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_schema-info.md b/docs/content/en/reference/cli/authelia/authelia_storage_schema-info.md index 2a4cd758b..ebecef02e 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_schema-info.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_schema-info.md @@ -43,8 +43,8 @@ authelia storage schema-info --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed4  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user.md b/docs/content/en/reference/cli/authelia/authelia_storage_user.md index 3a83e66d9..f179c61cd 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user.md @@ -37,8 +37,8 @@ authelia storage user --help  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers.md index 881667c15..f7ec634ef 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers.md @@ -37,8 +37,8 @@ authelia storage user identifiers --help  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_add.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_add.md index 3ea068d66..ff790e6c1 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_add.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_add.md @@ -46,8 +46,8 @@ authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_export.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_export.md index ea842f8fe..6dd117ca6 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_export.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_export.md @@ -38,15 +38,15 @@ authelia storage user identifiers export --file export.yaml --encryption-key b34  ### Options  ``` -  -f, --file string   The file name for the YAML export (default "user-opaque-identifiers.yml") +  -f, --file string   The file name for the YAML export (default "authelia.export.opaque-identifiers.yml")    -h, --help          help for export  ```  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_generate.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_generate.md index 29cd6befc..537408c65 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_generate.md @@ -48,8 +48,8 @@ authelia storage user identifiers generate --users john,mary --services openid -  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_import.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_import.md index 0b4b6ca2a..7993d2a82 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_import.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_identifiers_import.md @@ -26,30 +26,29 @@ The YAML file can either be automatically generated using the authelia storage u  manually provided the file is in the same format.  ``` -authelia storage user identifiers import [flags] +authelia storage user identifiers import <filename> [flags]  ```  ### Examples  ```  authelia storage user identifiers import -authelia storage user identifiers import --file export.yaml -authelia storage user identifiers import --file export.yaml --config config.yml -authelia storage user identifiers import --file export.yaml --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +authelia storage user identifiers import authelia.export.opaque-identifiers.yaml +authelia storage user identifiers import --config config.yml export.yaml +authelia storage user identifiers import --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw export.yaml  ```  ### Options  ``` -  -f, --file string   The file name for the YAML import (default "user-opaque-identifiers.yml") -  -h, --help          help for import +  -h, --help   help for import  ```  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp.md index 4319cb526..77e63483a 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp.md @@ -37,8 +37,8 @@ authelia storage user totp --help  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname @@ -64,4 +64,5 @@ authelia storage user totp --help  * [authelia storage user totp delete](authelia_storage_user_totp_delete.md)	 - Delete a TOTP configuration for a user  * [authelia storage user totp export](authelia_storage_user_totp_export.md)	 - Perform exports of the TOTP configurations  * [authelia storage user totp generate](authelia_storage_user_totp_generate.md)	 - Generate a TOTP configuration for a user +* [authelia storage user totp import](authelia_storage_user_totp_import.md)	 - Perform imports of the TOTP configurations diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_delete.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_delete.md index 8db359769..e4b637228 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_delete.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_delete.md @@ -43,8 +43,8 @@ authelia storage user totp delete john --encryption-key b3453fde-ecc2-4a1f-9422-  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export.md index 1986a771a..be40488ce 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export.md @@ -20,7 +20,7 @@ Perform exports of the TOTP configurations  Perform exports of the TOTP configurations. -This subcommand allows exporting TOTP configurations to various formats. +This subcommand allows exporting TOTP configurations to importable YAML files, or use the subcommands to export them to other non-importable formats.  ```  authelia storage user totp export [flags] @@ -29,25 +29,23 @@ authelia storage user totp export [flags]  ### Examples  ``` -authelia storage user totp export --format csv -authelia storage user totp export --format png --dir ./totp-qr -authelia storage user totp export --format png --dir ./totp-qr --config config.yml -authelia storage user totp export --format png --dir ./totp-qr --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +authelia storage user totp export --file example.yaml +authelia storage user totp export --config config.yml +authelia storage user totp export --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw  ```  ### Options  ``` -      --dir string      used with the png output format to specify which new directory to save the files in -      --format string   sets the output format, valid values are: csv, uri, png (default "uri") -  -h, --help            help for export +  -f, --file string   The file name for the YAML export (default "authelia.export.totp.yaml") +  -h, --help          help for export  ```  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname @@ -70,4 +68,7 @@ authelia storage user totp export --format png --dir ./totp-qr --encryption-key  ### SEE ALSO  * [authelia storage user totp](authelia_storage_user_totp.md)	 - Manage TOTP configurations +* [authelia storage user totp export csv](authelia_storage_user_totp_export_csv.md)	 - Perform exports of the TOTP configurations to a CSV +* [authelia storage user totp export png](authelia_storage_user_totp_export_png.md)	 - Perform exports of the TOTP configurations to QR code PNG images +* [authelia storage user totp export uri](authelia_storage_user_totp_export_uri.md)	 - Perform exports of the TOTP configurations to URIs diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_csv.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_csv.md new file mode 100644 index 000000000..bb80740ac --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_csv.md @@ -0,0 +1,71 @@ +--- +title: "authelia storage user totp export csv" +description: "Reference for the authelia storage user totp export csv command." +lead: "" +date: 2022-06-15T17:51:47+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 905 +toc: true +--- + +## authelia storage user totp export csv + +Perform exports of the TOTP configurations to a CSV + +### Synopsis + +Perform exports of the TOTP configurations to a CSV. + +This subcommand allows exporting TOTP configurations to a CSV. + +``` +authelia storage user totp export csv [flags] +``` + +### Examples + +``` +authelia storage user totp export csv --file users.csv +authelia storage user totp export csv --config config.yml +authelia storage user totp export csv --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -f, --file string   The file name for the CSV export (default "authelia.export.totp.csv") +  -h, --help          help for csv +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters' +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user totp export](authelia_storage_user_totp_export.md)	 - Perform exports of the TOTP configurations + diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_png.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_png.md new file mode 100644 index 000000000..4397dc959 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_png.md @@ -0,0 +1,72 @@ +--- +title: "authelia storage user totp export png" +description: "Reference for the authelia storage user totp export png command." +lead: "" +date: 2022-06-15T17:51:47+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 905 +toc: true +--- + +## authelia storage user totp export png + +Perform exports of the TOTP configurations to QR code PNG images + +### Synopsis + +Perform exports of the TOTP configurations to QR code PNG images. + +This subcommand allows exporting TOTP configurations to PNG images with QR codes which represent the appropriate URI so they can be scanned. + +``` +authelia storage user totp export png [flags] +``` + +### Examples + +``` +authelia storage user totp export png +authelia storage user totp export png --directory example/dir +authelia storage user totp export png --config config.yml +authelia storage user totp export png --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +      --directory string   The directory where all exported png files will be saved to +  -h, --help               help for png +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters' +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user totp export](authelia_storage_user_totp_export.md)	 - Perform exports of the TOTP configurations + diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_uri.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_uri.md new file mode 100644 index 000000000..640b65f9a --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_export_uri.md @@ -0,0 +1,70 @@ +--- +title: "authelia storage user totp export uri" +description: "Reference for the authelia storage user totp export uri command." +lead: "" +date: 2022-06-15T17:51:47+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 905 +toc: true +--- + +## authelia storage user totp export uri + +Perform exports of the TOTP configurations to URIs + +### Synopsis + +Perform exports of the TOTP configurations to URIs. + +This subcommand allows exporting TOTP configurations to TOTP URIs. + +``` +authelia storage user totp export uri [flags] +``` + +### Examples + +``` +authelia storage user totp export uri +authelia storage user totp export uri --config config.yml +authelia storage user totp export uri --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help   help for uri +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters' +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user totp export](authelia_storage_user_totp_export.md)	 - Perform exports of the TOTP configurations + diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_generate.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_generate.md index a5a3b150d..01de06534 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_generate.md @@ -55,8 +55,8 @@ authelia storage user totp generate john --algorithm SHA512 --config config.yml  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_import.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_import.md new file mode 100644 index 000000000..866c8c404 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_totp_import.md @@ -0,0 +1,70 @@ +--- +title: "authelia storage user totp import" +description: "Reference for the authelia storage user totp import command." +lead: "" +date: 2022-06-15T17:51:47+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 905 +toc: true +--- + +## authelia storage user totp import + +Perform imports of the TOTP configurations + +### Synopsis + +Perform imports of the TOTP configurations. + +This subcommand allows importing TOTP configurations from various formats. + +``` +authelia storage user totp import <filename> [flags] +``` + +### Examples + +``` +authelia storage user totp import authelia.export.totp.yaml +authelia storage user totp import --config config.yml authelia.export.totp.yaml +authelia storage user totp import --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw authelia.export.totp.yaml +``` + +### Options + +``` +  -h, --help   help for import +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters' +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user totp](authelia_storage_user_totp.md)	 - Manage TOTP configurations + diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn.md index e2fe634e1..5b08f4244 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn.md @@ -37,8 +37,8 @@ authelia storage user webauthn --help  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname @@ -61,6 +61,8 @@ authelia storage user webauthn --help  ### SEE ALSO  * [authelia storage user](authelia_storage_user.md)	 - Manages user settings -* [authelia storage user webauthn delete](authelia_storage_user_webauthn_delete.md)	 - Delete a WebAuthn device -* [authelia storage user webauthn list](authelia_storage_user_webauthn_list.md)	 - List WebAuthn devices +* [authelia storage user webauthn delete](authelia_storage_user_webauthn_delete.md)	 - Delete a Webauthn device +* [authelia storage user webauthn export](authelia_storage_user_webauthn_export.md)	 - Perform exports of the Webauthn devices +* [authelia storage user webauthn import](authelia_storage_user_webauthn_import.md)	 - Perform imports of the Webauthn devices +* [authelia storage user webauthn list](authelia_storage_user_webauthn_list.md)	 - List Webauthn devices diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_delete.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_delete.md index 66dfadd1c..aec44c2bf 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_delete.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_delete.md @@ -14,13 +14,13 @@ toc: true  ## authelia storage user webauthn delete -Delete a WebAuthn device +Delete a Webauthn device  ### Synopsis -Delete a WebAuthn device. +Delete a Webauthn device. -This subcommand allows deleting a WebAuthn device directly from the database. +This subcommand allows deleting a Webauthn device directly from the database.  ```  authelia storage user webauthn delete [username] [flags] @@ -52,8 +52,8 @@ authelia storage user webauthn delete --kid abc123 --encryption-key b3453fde-ecc  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_export.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_export.md new file mode 100644 index 000000000..81406c3ba --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_export.md @@ -0,0 +1,72 @@ +--- +title: "authelia storage user webauthn export" +description: "Reference for the authelia storage user webauthn export command." +lead: "" +date: 2022-06-15T17:51:47+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 905 +toc: true +--- + +## authelia storage user webauthn export + +Perform exports of the Webauthn devices + +### Synopsis + +Perform exports of the Webauthn devices. + +This subcommand allows exporting Webauthn devices to various formats. + +``` +authelia storage user webauthn export [flags] +``` + +### Examples + +``` +authelia storage user webauthn export +authelia storage user webauthn export --file authelia.export.webauthn.yaml +authelia storage user webauthn export --config config.yml +authelia storage user webauthn export--encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -f, --file string   The file name for the YAML export (default "authelia.export.webauthn.yaml") +  -h, --help          help for export +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters' +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user webauthn](authelia_storage_user_webauthn.md)	 - Manage Webauthn devices + diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_import.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_import.md new file mode 100644 index 000000000..3e967809c --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_import.md @@ -0,0 +1,71 @@ +--- +title: "authelia storage user webauthn import" +description: "Reference for the authelia storage user webauthn import command." +lead: "" +date: 2022-06-15T17:51:47+10:00 +draft: false +images: [] +menu: +  reference: +    parent: "cli-authelia" +weight: 905 +toc: true +--- + +## authelia storage user webauthn import + +Perform imports of the Webauthn devices + +### Synopsis + +Perform imports of the Webauthn devices. + +This subcommand allows importing Webauthn devices from various formats. + +``` +authelia storage user webauthn import <filename> [flags] +``` + +### Examples + +``` +authelia storage user webauthn export +authelia storage user webauthn import --file authelia.export.webauthn.yaml +authelia storage user webauthn import --file authelia.export.webauthn.yaml --config config.yml +authelia storage user webauthn import --file authelia.export.webauthn.yaml --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw +``` + +### Options + +``` +  -h, --help   help for import +``` + +### Options inherited from parent commands + +``` +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters' +      --encryption-key string                  the storage encryption key to use +      --mysql.database string                  the MySQL database name (default "authelia") +      --mysql.host string                      the MySQL hostname +      --mysql.password string                  the MySQL password +      --mysql.port int                         the MySQL port (default 3306) +      --mysql.username string                  the MySQL username (default "authelia") +      --postgres.database string               the PostgreSQL database name (default "authelia") +      --postgres.host string                   the PostgreSQL hostname +      --postgres.password string               the PostgreSQL password +      --postgres.port int                      the PostgreSQL port (default 5432) +      --postgres.schema string                 the PostgreSQL schema name (default "public") +      --postgres.ssl.certificate string        the PostgreSQL ssl certificate file location +      --postgres.ssl.key string                the PostgreSQL ssl key file location +      --postgres.ssl.mode string               the PostgreSQL ssl mode (default "disable") +      --postgres.ssl.root_certificate string   the PostgreSQL ssl root certificate file location +      --postgres.username string               the PostgreSQL username (default "authelia") +      --sqlite.path string                     the SQLite database path +``` + +### SEE ALSO + +* [authelia storage user webauthn](authelia_storage_user_webauthn.md)	 - Manage Webauthn devices + diff --git a/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_list.md b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_list.md index 6fc104b0f..9a1f569fa 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_list.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user_webauthn_list.md @@ -14,13 +14,13 @@ toc: true  ## authelia storage user webauthn list -List WebAuthn devices +List Webauthn devices  ### Synopsis -List WebAuthn devices. +List Webauthn devices. -This subcommand allows listing WebAuthn devices. +This subcommand allows listing Webauthn devices.  ```  authelia storage user webauthn list [username] [flags] @@ -46,8 +46,8 @@ authelia storage user webauthn list john --encryption-key b3453fde-ecc2-4a1f-942  ### Options inherited from parent commands  ``` -  -c, --config strings                         configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                         configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings    list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'        --encryption-key string                  the storage encryption key to use        --mysql.database string                  the MySQL database name (default "authelia")        --mysql.host string                      the MySQL hostname diff --git a/docs/content/en/reference/cli/authelia/authelia_validate-config.md b/docs/content/en/reference/cli/authelia/authelia_validate-config.md index 0ee461f98..0d7a586d8 100644 --- a/docs/content/en/reference/cli/authelia/authelia_validate-config.md +++ b/docs/content/en/reference/cli/authelia/authelia_validate-config.md @@ -43,8 +43,8 @@ authelia validate-config --config config.yml  ### Options inherited from parent commands  ``` -  -c, --config strings                        configuration files or directories to load (default [configuration.yml]) -      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information: authelia --help authelia filters +  -c, --config strings                        configuration files or directories to load, for more information run 'authelia -h authelia config' (default [configuration.yml]) +      --config.experimental.filters strings   list of filters to apply to all configuration files, for more information run 'authelia -h authelia filters'  ```  ### SEE ALSO diff --git a/internal/commands/const.go b/internal/commands/const.go index 6a1512d48..bd60b22d4 100644 --- a/internal/commands/const.go +++ b/internal/commands/const.go @@ -151,9 +151,9 @@ The YAML file can either be automatically generated using the authelia storage u  manually provided the file is in the same format.`  	cmdAutheliaStorageUserIdentifiersImportExample = `authelia storage user identifiers import -authelia storage user identifiers import --file export.yaml -authelia storage user identifiers import --file export.yaml --config config.yml -authelia storage user identifiers import --file export.yaml --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` +authelia storage user identifiers import authelia.export.opaque-identifiers.yaml +authelia storage user identifiers import --config config.yml export.yaml +authelia storage user identifiers import --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw export.yaml`  	cmdAutheliaStorageUserIdentifiersGenerateShort = "Generate opaque identifiers in bulk" @@ -177,34 +177,56 @@ This subcommand allows manually adding an opaque identifier for a user to the da  authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --config config.yml  authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` -	cmdAutheliaStorageUserWebAuthnShort = "Manage Webauthn devices" +	cmdAutheliaStorageUserWebauthnShort = "Manage Webauthn devices" -	cmdAutheliaStorageUserWebAuthnLong = `Manage Webauthn devices. +	cmdAutheliaStorageUserWebauthnLong = `Manage Webauthn devices.  This subcommand allows interacting with Webauthn devices.` -	cmdAutheliaStorageUserWebAuthnExample = `authelia storage user webauthn --help` +	cmdAutheliaStorageUserWebauthnExample = `authelia storage user webauthn --help` -	cmdAutheliaStorageUserWebAuthnListShort = "List WebAuthn devices" +	cmdAutheliaStorageUserWebauthnImportShort = "Perform imports of the Webauthn devices" -	cmdAutheliaStorageUserWebAuthnListLong = `List WebAuthn devices. +	cmdAutheliaStorageUserWebauthnImportLong = `Perform imports of the Webauthn devices. -This subcommand allows listing WebAuthn devices.` +This subcommand allows importing Webauthn devices from various formats.` -	cmdAutheliaStorageUserWebAuthnListExample = `authelia storage user webauthn list +	cmdAutheliaStorageUserWebauthnImportExample = `authelia storage user webauthn export +authelia storage user webauthn import --file authelia.export.webauthn.yaml +authelia storage user webauthn import --file authelia.export.webauthn.yaml --config config.yml +authelia storage user webauthn import --file authelia.export.webauthn.yaml --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` + +	cmdAutheliaStorageUserWebauthnExportShort = "Perform exports of the Webauthn devices" + +	cmdAutheliaStorageUserWebauthnExportLong = `Perform exports of the Webauthn devices. + +This subcommand allows exporting Webauthn devices to various formats.` + +	cmdAutheliaStorageUserWebauthnExportExample = `authelia storage user webauthn export +authelia storage user webauthn export --file authelia.export.webauthn.yaml +authelia storage user webauthn export --config config.yml +authelia storage user webauthn export--encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` + +	cmdAutheliaStorageUserWebauthnListShort = "List Webauthn devices" + +	cmdAutheliaStorageUserWebauthnListLong = `List Webauthn devices. + +This subcommand allows listing Webauthn devices.` + +	cmdAutheliaStorageUserWebauthnListExample = `authelia storage user webauthn list  authelia storage user webauthn list john  authelia storage user webauthn list --config config.yml  authelia storage user webauthn list john --config config.yml  authelia storage user webauthn list --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw  authelia storage user webauthn list john --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` -	cmdAutheliaStorageUserWebAuthnDeleteShort = "Delete a WebAuthn device" +	cmdAutheliaStorageUserWebauthnDeleteShort = "Delete a Webauthn device" -	cmdAutheliaStorageUserWebAuthnDeleteLong = `Delete a WebAuthn device. +	cmdAutheliaStorageUserWebauthnDeleteLong = `Delete a Webauthn device. -This subcommand allows deleting a WebAuthn device directly from the database.` +This subcommand allows deleting a Webauthn device directly from the database.` -	cmdAutheliaStorageUserWebAuthnDeleteExample = `authelia storage user webauthn delete john --all +	cmdAutheliaStorageUserWebauthnDeleteExample = `authelia storage user webauthn delete john --all  authelia storage user webauthn delete john --all --config config.yml  authelia storage user webauthn delete john --all --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw  authelia storage user webauthn delete john --description Primary @@ -246,16 +268,56 @@ This subcommand allows deleting a TOTP configuration directly from the database  authelia storage user totp delete john --config config.yml  authelia storage user totp delete john --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` +	cmdAutheliaStorageUserTOTPImportShort = "Perform imports of the TOTP configurations" + +	cmdAutheliaStorageUserTOTPImportLong = `Perform imports of the TOTP configurations. + +This subcommand allows importing TOTP configurations from various formats.` + +	cmdAutheliaStorageUserTOTPImportExample = `authelia storage user totp import authelia.export.totp.yaml +authelia storage user totp import --config config.yml authelia.export.totp.yaml +authelia storage user totp import --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw authelia.export.totp.yaml` +  	cmdAutheliaStorageUserTOTPExportShort = "Perform exports of the TOTP configurations"  	cmdAutheliaStorageUserTOTPExportLong = `Perform exports of the TOTP configurations. -This subcommand allows exporting TOTP configurations to various formats.` +This subcommand allows exporting TOTP configurations to importable YAML files, or use the subcommands to export them to other non-importable formats.` + +	cmdAutheliaStorageUserTOTPExportExample = `authelia storage user totp export --file example.yaml +authelia storage user totp export --config config.yml +authelia storage user totp export --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` + +	cmdAutheliaStorageUserTOTPExportCSVShort = "Perform exports of the TOTP configurations to a CSV" + +	cmdAutheliaStorageUserTOTPExportCSVLong = `Perform exports of the TOTP configurations to a CSV. + +This subcommand allows exporting TOTP configurations to a CSV.` -	cmdAutheliaStorageUserTOTPExportExample = `authelia storage user totp export --format csv -authelia storage user totp export --format png --dir ./totp-qr -authelia storage user totp export --format png --dir ./totp-qr --config config.yml -authelia storage user totp export --format png --dir ./totp-qr --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` +	cmdAutheliaStorageUserTOTPExportCSVExample = `authelia storage user totp export csv --file users.csv +authelia storage user totp export csv --config config.yml +authelia storage user totp export csv --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` + +	cmdAutheliaStorageUserTOTPExportURIShort = "Perform exports of the TOTP configurations to URIs" + +	cmdAutheliaStorageUserTOTPExportURILong = `Perform exports of the TOTP configurations to URIs. + +This subcommand allows exporting TOTP configurations to TOTP URIs.` + +	cmdAutheliaStorageUserTOTPExportURIExample = `authelia storage user totp export uri +authelia storage user totp export uri --config config.yml +authelia storage user totp export uri --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw` + +	cmdAutheliaStorageUserTOTPExportPNGShort = "Perform exports of the TOTP configurations to QR code PNG images" + +	cmdAutheliaStorageUserTOTPExportPNGLong = `Perform exports of the TOTP configurations to QR code PNG images. + +This subcommand allows exporting TOTP configurations to PNG images with QR codes which represent the appropriate URI so they can be scanned.` + +	cmdAutheliaStorageUserTOTPExportPNGExample = `authelia storage user totp export png +authelia storage user totp export png --directory example/dir +authelia storage user totp export png --config config.yml +authelia storage user totp export png --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`  	cmdAutheliaStorageSchemaInfoShort = "Show the storage information" @@ -472,16 +534,6 @@ const (  )  const ( -	storageTOTPExportFormatCSV = "csv" -	storageTOTPExportFormatURI = "uri" -	storageTOTPExportFormatPNG = "png" -) - -var ( -	validStorageTOTPExportFormats = []string{storageTOTPExportFormatCSV, storageTOTPExportFormatURI, storageTOTPExportFormatPNG} -) - -const (  	timeLayoutCertificateNotBefore = "Jan 2 15:04:05 2006"  ) @@ -571,7 +623,6 @@ const (  	cmdFlagNameAlgorithm   = "algorithm"  	cmdFlagNameIssuer      = "issuer"  	cmdFlagNameForce       = "force" -	cmdFlagNameFormat      = "format"  	cmdFlagNamePath        = "path"  	cmdFlagNameTarget      = "target"  	cmdFlagNameDestroyData = "destroy-data" @@ -599,6 +650,9 @@ const (  	cmdUseHashBCrypt    = "bcrypt"  	cmdUseHashSCrypt    = "scrypt" +	cmdUseExport         = "export" +	cmdUseImportFileName = "import <filename>" +  	cmdUseCrypto      = "crypto"  	cmdUseRand        = "rand"  	cmdUseCertificate = "certificate" diff --git a/internal/commands/context.go b/internal/commands/context.go index edb79bc1e..ea3026759 100644 --- a/internal/commands/context.go +++ b/internal/commands/context.go @@ -24,6 +24,7 @@ import (  	"github.com/authelia/authelia/v4/internal/oidc"  	"github.com/authelia/authelia/v4/internal/regulation"  	"github.com/authelia/authelia/v4/internal/session" +	"github.com/authelia/authelia/v4/internal/storage"  	"github.com/authelia/authelia/v4/internal/templates"  	"github.com/authelia/authelia/v4/internal/totp"  	"github.com/authelia/authelia/v4/internal/utils" @@ -80,7 +81,6 @@ type CmdCtxConfig struct {  // CobraRunECmd describes a function that can be used as a *cobra.Command RunE, PreRunE, or PostRunE.  type CobraRunECmd func(cmd *cobra.Command, args []string) (err error) -// CheckSchemaVersion is a utility function which checks the schema version.  func (ctx *CmdCtx) CheckSchemaVersion() (err error) {  	if ctx.providers.StorageProvider == nil {  		return fmt.Errorf("storage not loaded") @@ -106,6 +106,25 @@ func (ctx *CmdCtx) CheckSchemaVersion() (err error) {  	}  } +// CheckSchema is a utility function which checks the schema version and encryption key. +func (ctx *CmdCtx) CheckSchema() (err error) { +	if err = ctx.CheckSchemaVersion(); err != nil { +		return err +	} + +	var result storage.EncryptionValidationResult + +	if result, err = ctx.providers.StorageProvider.SchemaEncryptionCheckKey(ctx, false); !result.Checked() || !result.Success() { +		if err != nil { +			return fmt.Errorf("failed to check the schema encryption key: %w", err) +		} + +		return fmt.Errorf("failed to check the schema encryption key: the key is not valid for the schema") +	} + +	return nil +} +  // LoadTrustedCertificates loads the trusted certificates into the CmdCtx.  func (ctx *CmdCtx) LoadTrustedCertificates() (warns, errs []error) {  	ctx.trusted, warns, errs = utils.NewX509CertPool(ctx.config.CertificatesDirectory) diff --git a/internal/commands/crypto_hash.go b/internal/commands/crypto_hash.go index 3eb4fa374..7c85f3ef3 100644 --- a/internal/commands/crypto_hash.go +++ b/internal/commands/crypto_hash.go @@ -63,7 +63,7 @@ func newCryptoHashGenerateCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Example: cmdAutheliaCryptoHashGenerateExample,  		PreRunE: ctx.ChainRunE(  			ctx.ConfigSetDefaultsRunE(defaults), -			ctx.CryptoHashGenerateMapFlagsPreRunE, +			ctx.CryptoHashGenerateMapFlagsRunE,  			ctx.ConfigLoadRunE,  			ctx.ConfigValidateSectionPasswordRunE,  		), @@ -116,7 +116,7 @@ func newCryptoHashGenerateSubCmd(ctx *CmdCtx, use string) (cmd *cobra.Command) {  		Args:    cobra.NoArgs,  		PersistentPreRunE: ctx.ChainRunE(  			ctx.ConfigSetDefaultsRunE(defaults), -			ctx.CryptoHashGenerateMapFlagsPreRunE, +			ctx.CryptoHashGenerateMapFlagsRunE,  			ctx.ConfigLoadRunE,  			ctx.ConfigValidateSectionPasswordRunE,  		), @@ -207,9 +207,9 @@ func (ctx *CmdCtx) CryptoHashValidateRunE(cmd *cobra.Command, args []string) (er  	return nil  } -// CryptoHashGenerateMapFlagsPreRunE is the RunE which configures the flags map configuration source for the +// CryptoHashGenerateMapFlagsRunE is the RunE which configures the flags map configuration source for the  // authelia crypto hash generate commands. -func (ctx *CmdCtx) CryptoHashGenerateMapFlagsPreRunE(cmd *cobra.Command, args []string) (err error) { +func (ctx *CmdCtx) CryptoHashGenerateMapFlagsRunE(cmd *cobra.Command, args []string) (err error) {  	var flagsMap map[string]string  	switch cmd.Use { diff --git a/internal/commands/storage.go b/internal/commands/storage.go index 8a7129b79..b201af5df 100644 --- a/internal/commands/storage.go +++ b/internal/commands/storage.go @@ -15,13 +15,13 @@ func newStorageCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageShort,  		Long:    cmdAutheliaStorageLong,  		Example: cmdAutheliaStorageExample, -		Args:    cobra.NoArgs,  		PersistentPreRunE: ctx.ChainRunE( -			ctx.ConfigStorageCommandLineConfigPersistentPreRunE, +			ctx.ConfigStorageCommandLineConfigRunE,  			ctx.ConfigLoadRunE, -			ctx.ConfigValidateStoragePersistentPreRunE, +			ctx.ConfigValidateStorageRunE,  			ctx.LoadProvidersStorageRunE,  		), +		Args: cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -63,6 +63,7 @@ func newStorageEncryptionCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageEncryptionShort,  		Long:    cmdAutheliaStorageEncryptionLong,  		Example: cmdAutheliaStorageEncryptionExample, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -82,6 +83,7 @@ func newStorageEncryptionCheckCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Long:    cmdAutheliaStorageEncryptionCheckLong,  		Example: cmdAutheliaStorageEncryptionCheckExample,  		RunE:    ctx.StorageSchemaEncryptionCheckRunE, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -98,6 +100,7 @@ func newStorageEncryptionChangeKeyCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Long:    cmdAutheliaStorageEncryptionChangeKeyLong,  		Example: cmdAutheliaStorageEncryptionChangeKeyExample,  		RunE:    ctx.StorageSchemaEncryptionChangeKeyRunE, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -113,6 +116,7 @@ func newStorageUserCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageUserShort,  		Long:    cmdAutheliaStorageUserLong,  		Example: cmdAutheliaStorageUserExample, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -120,7 +124,7 @@ func newStorageUserCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	cmd.AddCommand(  		newStorageUserIdentifiersCmd(ctx),  		newStorageUserTOTPCmd(ctx), -		newStorageUserWebAuthnCmd(ctx), +		newStorageUserWebauthnCmd(ctx),  	)  	return cmd @@ -132,6 +136,7 @@ func newStorageUserIdentifiersCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageUserIdentifiersShort,  		Long:    cmdAutheliaStorageUserIdentifiersLong,  		Example: cmdAutheliaStorageUserIdentifiersExample, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -148,33 +153,33 @@ func newStorageUserIdentifiersCmd(ctx *CmdCtx) (cmd *cobra.Command) {  func newStorageUserIdentifiersExportCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	cmd = &cobra.Command{ -		Use:     "export", +		Use:     cmdUseExport,  		Short:   cmdAutheliaStorageUserIdentifiersExportShort,  		Long:    cmdAutheliaStorageUserIdentifiersExportLong,  		Example: cmdAutheliaStorageUserIdentifiersExportExample,  		RunE:    ctx.StorageUserIdentifiersExportRunE, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} -	cmd.Flags().StringP(cmdFlagNameFile, "f", "user-opaque-identifiers.yml", "The file name for the YAML export") +	cmd.Flags().StringP(cmdFlagNameFile, "f", "authelia.export.opaque-identifiers.yml", "The file name for the YAML export")  	return cmd  }  func newStorageUserIdentifiersImportCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	cmd = &cobra.Command{ -		Use:     "import", +		Use:     cmdUseImportFileName,  		Short:   cmdAutheliaStorageUserIdentifiersImportShort,  		Long:    cmdAutheliaStorageUserIdentifiersImportLong,  		Example: cmdAutheliaStorageUserIdentifiersImportExample,  		RunE:    ctx.StorageUserIdentifiersImportRunE, +		Args:    cobra.ExactArgs(1),  		DisableAutoGenTag: true,  	} -	cmd.Flags().StringP(cmdFlagNameFile, "f", "user-opaque-identifiers.yml", "The file name for the YAML import") -  	return cmd  } @@ -185,6 +190,7 @@ func newStorageUserIdentifiersGenerateCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Long:    cmdAutheliaStorageUserIdentifiersGenerateLong,  		Example: cmdAutheliaStorageUserIdentifiersGenerateExample,  		RunE:    ctx.StorageUserIdentifiersGenerateRunE, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -202,8 +208,8 @@ func newStorageUserIdentifiersAddCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageUserIdentifiersAddShort,  		Long:    cmdAutheliaStorageUserIdentifiersAddLong,  		Example: cmdAutheliaStorageUserIdentifiersAddExample, -		Args:    cobra.ExactArgs(1),  		RunE:    ctx.StorageUserIdentifiersAddRunE, +		Args:    cobra.ExactArgs(1),  		DisableAutoGenTag: true,  	} @@ -215,31 +221,66 @@ func newStorageUserIdentifiersAddCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	return cmd  } -func newStorageUserWebAuthnCmd(ctx *CmdCtx) (cmd *cobra.Command) { +func newStorageUserWebauthnCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	cmd = &cobra.Command{  		Use:     "webauthn", -		Short:   cmdAutheliaStorageUserWebAuthnShort, -		Long:    cmdAutheliaStorageUserWebAuthnLong, -		Example: cmdAutheliaStorageUserWebAuthnExample, +		Short:   cmdAutheliaStorageUserWebauthnShort, +		Long:    cmdAutheliaStorageUserWebauthnLong, +		Example: cmdAutheliaStorageUserWebauthnExample, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	}  	cmd.AddCommand( -		newStorageUserWebAuthnListCmd(ctx), -		newStorageUserWebAuthnDeleteCmd(ctx), +		newStorageUserWebauthnListCmd(ctx), +		newStorageUserWebauthnDeleteCmd(ctx), +		newStorageUserWebauthnExportCmd(ctx), +		newStorageUserWebauthnImportCmd(ctx),  	)  	return cmd  } -func newStorageUserWebAuthnListCmd(ctx *CmdCtx) (cmd *cobra.Command) { +func newStorageUserWebauthnImportCmd(ctx *CmdCtx) (cmd *cobra.Command) { +	cmd = &cobra.Command{ +		Use:     cmdUseImportFileName, +		Short:   cmdAutheliaStorageUserWebauthnImportShort, +		Long:    cmdAutheliaStorageUserWebauthnImportLong, +		Example: cmdAutheliaStorageUserWebauthnImportExample, +		RunE:    ctx.StorageUserWebauthnImportRunE, +		Args:    cobra.ExactArgs(1), + +		DisableAutoGenTag: true, +	} + +	return cmd +} + +func newStorageUserWebauthnExportCmd(ctx *CmdCtx) (cmd *cobra.Command) { +	cmd = &cobra.Command{ +		Use:     cmdUseExport, +		Short:   cmdAutheliaStorageUserWebauthnExportShort, +		Long:    cmdAutheliaStorageUserWebauthnExportLong, +		Example: cmdAutheliaStorageUserWebauthnExportExample, +		RunE:    ctx.StorageUserWebauthnExportRunE, +		Args:    cobra.NoArgs, + +		DisableAutoGenTag: true, +	} + +	cmd.Flags().StringP(cmdFlagNameFile, "f", "authelia.export.webauthn.yaml", "The file name for the YAML export") + +	return cmd +} + +func newStorageUserWebauthnListCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	cmd = &cobra.Command{  		Use:     "list [username]", -		Short:   cmdAutheliaStorageUserWebAuthnListShort, -		Long:    cmdAutheliaStorageUserWebAuthnListLong, -		Example: cmdAutheliaStorageUserWebAuthnListExample, -		RunE:    ctx.StorageWebauthnListRunE, +		Short:   cmdAutheliaStorageUserWebauthnListShort, +		Long:    cmdAutheliaStorageUserWebauthnListLong, +		Example: cmdAutheliaStorageUserWebauthnListExample, +		RunE:    ctx.StorageUserWebauthnListRunE,  		Args:    cobra.MaximumNArgs(1),  		DisableAutoGenTag: true, @@ -248,13 +289,13 @@ func newStorageUserWebAuthnListCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	return cmd  } -func newStorageUserWebAuthnDeleteCmd(ctx *CmdCtx) (cmd *cobra.Command) { +func newStorageUserWebauthnDeleteCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	cmd = &cobra.Command{  		Use:     "delete [username]", -		Short:   cmdAutheliaStorageUserWebAuthnDeleteShort, -		Long:    cmdAutheliaStorageUserWebAuthnDeleteLong, -		Example: cmdAutheliaStorageUserWebAuthnDeleteExample, -		RunE:    ctx.StorageWebauthnDeleteRunE, +		Short:   cmdAutheliaStorageUserWebauthnDeleteShort, +		Long:    cmdAutheliaStorageUserWebauthnDeleteLong, +		Example: cmdAutheliaStorageUserWebauthnDeleteExample, +		RunE:    ctx.StorageUserWebauthnDeleteRunE,  		Args:    cobra.MaximumNArgs(1),  		DisableAutoGenTag: true, @@ -273,6 +314,7 @@ func newStorageUserTOTPCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageUserTOTPShort,  		Long:    cmdAutheliaStorageUserTOTPLong,  		Example: cmdAutheliaStorageUserTOTPExample, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -281,6 +323,7 @@ func newStorageUserTOTPCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		newStorageUserTOTPGenerateCmd(ctx),  		newStorageUserTOTPDeleteCmd(ctx),  		newStorageUserTOTPExportCmd(ctx), +		newStorageUserTOTPImportCmd(ctx),  	)  	return cmd @@ -292,7 +335,7 @@ func newStorageUserTOTPGenerateCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageUserTOTPGenerateShort,  		Long:    cmdAutheliaStorageUserTOTPGenerateLong,  		Example: cmdAutheliaStorageUserTOTPGenerateExample, -		RunE:    ctx.StorageTOTPGenerateRunE, +		RunE:    ctx.StorageUserTOTPGenerateRunE,  		Args:    cobra.ExactArgs(1),  		DisableAutoGenTag: true, @@ -316,7 +359,22 @@ func newStorageUserTOTPDeleteCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageUserTOTPDeleteShort,  		Long:    cmdAutheliaStorageUserTOTPDeleteLong,  		Example: cmdAutheliaStorageUserTOTPDeleteExample, -		RunE:    ctx.StorageTOTPDeleteRunE, +		RunE:    ctx.StorageUserTOTPDeleteRunE, +		Args:    cobra.ExactArgs(1), + +		DisableAutoGenTag: true, +	} + +	return cmd +} + +func newStorageUserTOTPImportCmd(ctx *CmdCtx) (cmd *cobra.Command) { +	cmd = &cobra.Command{ +		Use:     cmdUseImportFileName, +		Short:   cmdAutheliaStorageUserTOTPImportShort, +		Long:    cmdAutheliaStorageUserTOTPImportLong, +		Example: cmdAutheliaStorageUserTOTPImportExample, +		RunE:    ctx.StorageUserTOTPImportRunE,  		Args:    cobra.ExactArgs(1),  		DisableAutoGenTag: true, @@ -327,17 +385,72 @@ func newStorageUserTOTPDeleteCmd(ctx *CmdCtx) (cmd *cobra.Command) {  func newStorageUserTOTPExportCmd(ctx *CmdCtx) (cmd *cobra.Command) {  	cmd = &cobra.Command{ -		Use:     "export", +		Use:     cmdUseExport,  		Short:   cmdAutheliaStorageUserTOTPExportShort,  		Long:    cmdAutheliaStorageUserTOTPExportLong,  		Example: cmdAutheliaStorageUserTOTPExportExample, -		RunE:    ctx.StorageTOTPExportRunE, +		RunE:    ctx.StorageUserTOTPExportRunE, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} -	cmd.Flags().String(cmdFlagNameFormat, storageTOTPExportFormatURI, fmt.Sprintf("sets the output format, valid values are: %s", strings.Join(validStorageTOTPExportFormats, ", "))) -	cmd.Flags().String("dir", "", "used with the png output format to specify which new directory to save the files in") +	cmd.AddCommand( +		newStorageUserTOTPExportCSVCmd(ctx), +		newStorageUserTOTPExportPNGCmd(ctx), +		newStorageUserTOTPExportURICmd(ctx), +	) + +	cmd.Flags().StringP(cmdFlagNameFile, "f", "authelia.export.totp.yaml", "The file name for the YAML export") + +	return cmd +} + +func newStorageUserTOTPExportURICmd(ctx *CmdCtx) (cmd *cobra.Command) { +	cmd = &cobra.Command{ +		Use:     "uri", +		Short:   cmdAutheliaStorageUserTOTPExportURIShort, +		Long:    cmdAutheliaStorageUserTOTPExportURILong, +		Example: cmdAutheliaStorageUserTOTPExportURIExample, +		RunE:    ctx.StorageUserTOTPExportURIRunE, +		Args:    cobra.NoArgs, + +		DisableAutoGenTag: true, +	} + +	return cmd +} + +func newStorageUserTOTPExportCSVCmd(ctx *CmdCtx) (cmd *cobra.Command) { +	cmd = &cobra.Command{ +		Use:     "csv", +		Short:   cmdAutheliaStorageUserTOTPExportCSVShort, +		Long:    cmdAutheliaStorageUserTOTPExportCSVLong, +		Example: cmdAutheliaStorageUserTOTPExportCSVExample, +		RunE:    ctx.StorageUserTOTPExportCSVRunE, +		Args:    cobra.NoArgs, + +		DisableAutoGenTag: true, +	} + +	cmd.Flags().StringP(cmdFlagNameFile, "f", "authelia.export.totp.csv", "The file name for the CSV export") + +	return cmd +} + +func newStorageUserTOTPExportPNGCmd(ctx *CmdCtx) (cmd *cobra.Command) { +	cmd = &cobra.Command{ +		Use:     "png", +		Short:   cmdAutheliaStorageUserTOTPExportPNGShort, +		Long:    cmdAutheliaStorageUserTOTPExportPNGLong, +		Example: cmdAutheliaStorageUserTOTPExportPNGExample, +		RunE:    ctx.StorageUserTOTPExportPNGRunE, +		Args:    cobra.NoArgs, + +		DisableAutoGenTag: true, +	} + +	cmd.Flags().String(cmdFlagNameDirectory, "", "The directory where all exported png files will be saved to")  	return cmd  } @@ -349,6 +462,7 @@ func newStorageSchemaInfoCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Long:    cmdAutheliaStorageSchemaInfoLong,  		Example: cmdAutheliaStorageSchemaInfoExample,  		RunE:    ctx.StorageSchemaInfoRunE, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -383,8 +497,8 @@ func newStorageMigrateHistoryCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageMigrateHistoryShort,  		Long:    cmdAutheliaStorageMigrateHistoryLong,  		Example: cmdAutheliaStorageMigrateHistoryExample, -		Args:    cobra.NoArgs,  		RunE:    ctx.StorageMigrateHistoryRunE, +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -398,8 +512,8 @@ func newStorageMigrateListUpCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageMigrateListUpShort,  		Long:    cmdAutheliaStorageMigrateListUpLong,  		Example: cmdAutheliaStorageMigrateListUpExample, -		Args:    cobra.NoArgs,  		RunE:    ctx.NewStorageMigrateListRunE(true), +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -413,8 +527,8 @@ func newStorageMigrateListDownCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageMigrateListDownShort,  		Long:    cmdAutheliaStorageMigrateListDownLong,  		Example: cmdAutheliaStorageMigrateListDownExample, -		Args:    cobra.NoArgs,  		RunE:    ctx.NewStorageMigrateListRunE(false), +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -428,8 +542,8 @@ func newStorageMigrateUpCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageMigrateUpShort,  		Long:    cmdAutheliaStorageMigrateUpLong,  		Example: cmdAutheliaStorageMigrateUpExample, -		Args:    cobra.NoArgs,  		RunE:    ctx.NewStorageMigrationRunE(true), +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} @@ -445,8 +559,8 @@ func newStorageMigrateDownCmd(ctx *CmdCtx) (cmd *cobra.Command) {  		Short:   cmdAutheliaStorageMigrateDownShort,  		Long:    cmdAutheliaStorageMigrateDownLong,  		Example: cmdAutheliaStorageMigrateDownExample, -		Args:    cobra.NoArgs,  		RunE:    ctx.NewStorageMigrationRunE(false), +		Args:    cobra.NoArgs,  		DisableAutoGenTag: true,  	} diff --git a/internal/commands/storage_run.go b/internal/commands/storage_run.go index 42103dd6a..d2033767c 100644 --- a/internal/commands/storage_run.go +++ b/internal/commands/storage_run.go @@ -1,6 +1,7 @@  package commands  import ( +	"bytes"  	"database/sql"  	"errors"  	"fmt" @@ -48,8 +49,8 @@ func (ctx *CmdCtx) LoadProvidersStorageRunE(cmd *cobra.Command, args []string) (  	}  } -// ConfigStorageCommandLineConfigPersistentPreRunE configures the storage command mapping. -func (ctx *CmdCtx) ConfigStorageCommandLineConfigPersistentPreRunE(cmd *cobra.Command, _ []string) (err error) { +// ConfigStorageCommandLineConfigRunE configures the storage command mapping. +func (ctx *CmdCtx) ConfigStorageCommandLineConfigRunE(cmd *cobra.Command, _ []string) (err error) {  	flagsMap := map[string]string{  		cmdFlagNameEncryptionKey: "storage.encryption_key", @@ -82,8 +83,8 @@ func (ctx *CmdCtx) ConfigStorageCommandLineConfigPersistentPreRunE(cmd *cobra.Co  	return ctx.ConfigSetFlagsMapRunE(cmd.Flags(), flagsMap, true, false)  } -// ConfigValidateStoragePersistentPreRunE validates the storage config before running commands using it. -func (ctx *CmdCtx) ConfigValidateStoragePersistentPreRunE(_ *cobra.Command, _ []string) (err error) { +// ConfigValidateStorageRunE validates the storage config before running commands using it. +func (ctx *CmdCtx) ConfigValidateStorageRunE(_ *cobra.Command, _ []string) (err error) {  	if errs := ctx.cconfig.validator.Errors(); len(errs) != 0 {  		var (  			i int @@ -128,15 +129,15 @@ func (ctx *CmdCtx) ConfigValidateStoragePersistentPreRunE(_ *cobra.Command, _ []  }  func (ctx *CmdCtx) StorageSchemaEncryptionCheckRunE(cmd *cobra.Command, args []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() +  	var (  		verbose bool  		result  storage.EncryptionValidationResult  	) -	defer func() { -		_ = ctx.providers.StorageProvider.Close() -	}() -  	if err = ctx.CheckSchemaVersion(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} @@ -185,16 +186,16 @@ func (ctx *CmdCtx) StorageSchemaEncryptionCheckRunE(cmd *cobra.Command, args []s  // StorageSchemaEncryptionChangeKeyRunE is the RunE for the authelia storage encryption change-key command.  func (ctx *CmdCtx) StorageSchemaEncryptionChangeKeyRunE(cmd *cobra.Command, args []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() +  	var (  		key     string  		version int  	) -	defer func() { -		_ = ctx.providers.StorageProvider.Close() -	}() - -	if err = ctx.CheckSchemaVersion(); err != nil { +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} @@ -235,17 +236,312 @@ func (ctx *CmdCtx) StorageSchemaEncryptionChangeKeyRunE(cmd *cobra.Command, args  	return nil  } -// StorageWebauthnListRunE is the RunE for the authelia storage user webauthn list command. -func (ctx *CmdCtx) StorageWebauthnListRunE(cmd *cobra.Command, args []string) (err error) { -	if len(args) == 0 || args[0] == "" { -		return ctx.StorageWebauthnListAllRunE(cmd, args) +// StorageMigrateHistoryRunE is the RunE for the authelia storage migrate history command. +func (ctx *CmdCtx) StorageMigrateHistoryRunE(_ *cobra.Command, _ []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() + +	var ( +		version    int +		migrations []model.Migration +	) + +	if version, err = ctx.providers.StorageProvider.SchemaVersion(ctx); err != nil { +		return err +	} + +	if version <= 0 { +		fmt.Println("No migration history is available for schemas that not version 1 or above.") +		return +	} + +	if migrations, err = ctx.providers.StorageProvider.SchemaMigrationHistory(ctx); err != nil { +		return err +	} + +	if len(migrations) == 0 { +		return errors.New("no migration history found which may indicate a broken schema")  	} +	fmt.Printf("Migration History:\n\nID\tDate\t\t\t\tBefore\tAfter\tAuthelia Version\n") + +	for _, m := range migrations { +		fmt.Printf("%d\t%s\t%d\t%d\t%s\n", m.ID, m.Applied.Format("2006-01-02 15:04:05 -0700"), m.Before, m.After, m.Version) +	} + +	return nil +} + +// NewStorageMigrateListRunE creates the RunE for the authelia storage migrate list command. +func (ctx *CmdCtx) NewStorageMigrateListRunE(up bool) func(cmd *cobra.Command, args []string) (err error) { +	return func(cmd *cobra.Command, args []string) (err error) { +		defer func() { +			_ = ctx.providers.StorageProvider.Close() +		}() + +		var ( +			migrations   []model.SchemaMigration +			directionStr string +		) + +		if up { +			migrations, err = ctx.providers.StorageProvider.SchemaMigrationsUp(ctx, 0) +			directionStr = "Up" +		} else { +			migrations, err = ctx.providers.StorageProvider.SchemaMigrationsDown(ctx, 0) +			directionStr = "Down" +		} + +		if err != nil && !errors.Is(err, storage.ErrNoAvailableMigrations) && !errors.Is(err, storage.ErrMigrateCurrentVersionSameAsTarget) { +			return err +		} + +		if len(migrations) == 0 { +			fmt.Printf("Storage Schema Migration List (%s)\n\nNo Migrations Available\n", directionStr) +		} else { +			fmt.Printf("Storage Schema Migration List (%s)\n\nVersion\t\tDescription\n", directionStr) + +			for _, migration := range migrations { +				fmt.Printf("%d\t\t%s\n", migration.Version, migration.Name) +			} +		} + +		return nil +	} +} + +// NewStorageMigrationRunE creates the RunE for the authelia storage migrate command. +func (ctx *CmdCtx) NewStorageMigrationRunE(up bool) func(cmd *cobra.Command, args []string) (err error) { +	return func(cmd *cobra.Command, args []string) (err error) { +		defer func() { +			_ = ctx.providers.StorageProvider.Close() +		}() + +		var ( +			target int +		) + +		if target, err = cmd.Flags().GetInt(cmdFlagNameTarget); err != nil { +			return err +		} + +		switch { +		case up: +			switch cmd.Flags().Changed(cmdFlagNameTarget) { +			case true: +				return ctx.providers.StorageProvider.SchemaMigrate(ctx, true, target) +			default: +				return ctx.providers.StorageProvider.SchemaMigrate(ctx, true, storage.SchemaLatest) +			} +		default: +			if !cmd.Flags().Changed(cmdFlagNameTarget) { +				return errors.New("you must set a target version") +			} + +			var confirmed bool + +			if confirmed, err = termReadConfirmation(cmd.Flags(), cmdFlagNameDestroyData, "Schema Down Migrations may DESTROY data, type 'DESTROY' and press return to continue: ", "DESTROY"); err != nil { +				return err +			} + +			if !confirmed { +				return errors.New("cancelling down migration due to user not accepting data destruction") +			} + +			return ctx.providers.StorageProvider.SchemaMigrate(ctx, false, target) +		} +	} +} + +// StorageSchemaInfoRunE is the RunE for the authelia storage schema info command. +func (ctx *CmdCtx) StorageSchemaInfoRunE(_ *cobra.Command, _ []string) (err error) {  	defer func() {  		_ = ctx.providers.StorageProvider.Close()  	}() -	if err = ctx.CheckSchemaVersion(); err != nil { +	var ( +		upgradeStr, tablesStr string + +		tables          []string +		version, latest int +	) + +	if version, err = ctx.providers.StorageProvider.SchemaVersion(ctx); err != nil && err.Error() != "unknown schema state" { +		return err +	} + +	if tables, err = ctx.providers.StorageProvider.SchemaTables(ctx); err != nil { +		return err +	} + +	if len(tables) == 0 { +		tablesStr = "N/A" +	} else { +		tablesStr = strings.Join(tables, ", ") +	} + +	if latest, err = ctx.providers.StorageProvider.SchemaLatestVersion(); err != nil { +		return err +	} + +	if latest > version { +		upgradeStr = fmt.Sprintf("yes - version %d", latest) +	} else { +		upgradeStr = "no" +	} + +	var ( +		encryption string +		result     storage.EncryptionValidationResult +	) + +	switch result, err = ctx.providers.StorageProvider.SchemaEncryptionCheckKey(ctx, false); { +	case err != nil: +		if errors.Is(err, storage.ErrSchemaEncryptionVersionUnsupported) { +			encryption = "unsupported (schema version)" +		} else { +			encryption = invalid +		} +	case !result.Success(): +		encryption = invalid +	default: +		encryption = "valid" +	} + +	fmt.Printf("Schema Version: %s\nSchema Upgrade Available: %s\nSchema Tables: %s\nSchema Encryption Key: %s\n", storage.SchemaVersionToString(version), upgradeStr, tablesStr, encryption) + +	return nil +} + +func (ctx *CmdCtx) StorageUserWebauthnExportRunE(cmd *cobra.Command, args []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() + +	if err = ctx.CheckSchema(); err != nil { +		return storageWrapCheckSchemaErr(err) +	} + +	var ( +		filename string +	) + +	if filename, err = cmd.Flags().GetString(cmdFlagNameFile); err != nil { +		return err +	} + +	switch _, err = os.Stat(filename); { +	case err == nil: +		return fmt.Errorf("must specify a file that doesn't exist but '%s' exists", filename) +	case !os.IsNotExist(err): +		return fmt.Errorf("error occurred opening '%s': %w", filename, err) +	} + +	limit := 10 +	count := 0 + +	var ( +		devices []model.WebauthnDevice +	) + +	export := &model.WebauthnDeviceExport{ +		WebauthnDevices: nil, +	} + +	for page := 0; true; page++ { +		if devices, err = ctx.providers.StorageProvider.LoadWebauthnDevices(ctx, limit, page); err != nil { +			return err +		} + +		export.WebauthnDevices = append(export.WebauthnDevices, devices...) + +		l := len(devices) + +		count += l + +		if l < limit { +			break +		} +	} + +	var data []byte + +	if data, err = yaml.Marshal(export); err != nil { +		return fmt.Errorf("error occurred marshalling data to YAML: %w", err) +	} + +	if err = os.WriteFile(filename, data, 0600); err != nil { +		return fmt.Errorf("error occurred writing to file '%s': %w", filename, err) +	} + +	fmt.Printf(cliOutputFmtSuccessfulUserExportFile, count, "Webauthn devices", "YAML", filename) + +	return nil +} + +func (ctx *CmdCtx) StorageUserWebauthnImportRunE(cmd *cobra.Command, args []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() + +	var ( +		filename string + +		stat os.FileInfo +		data []byte +	) + +	filename = args[0] + +	if stat, err = os.Stat(filename); err != nil { +		return fmt.Errorf("must specify a filename that exists but '%s' had an error opening it: %w", filename, err) +	} + +	if stat.IsDir() { +		return fmt.Errorf("must specify a filename that exists but '%s' is a directory", filename) +	} + +	if data, err = os.ReadFile(filename); err != nil { +		return err +	} + +	export := &model.WebauthnDeviceExport{} + +	if err = yaml.Unmarshal(data, export); err != nil { +		return err +	} + +	if len(export.WebauthnDevices) == 0 { +		return fmt.Errorf("can't import a YAML file without Webauthn devices data") +	} + +	if err = ctx.CheckSchema(); err != nil { +		return storageWrapCheckSchemaErr(err) +	} + +	for _, device := range export.WebauthnDevices { +		if err = ctx.providers.StorageProvider.SaveWebauthnDevice(ctx, device); err != nil { +			return err +		} +	} + +	fmt.Printf(cliOutputFmtSuccessfulUserImportFile, len(export.WebauthnDevices), "Webauthn devices", "YAML", filename) + +	return nil +} + +// StorageUserWebauthnListRunE is the RunE for the authelia storage user webauthn list command. +func (ctx *CmdCtx) StorageUserWebauthnListRunE(cmd *cobra.Command, args []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() + +	if len(args) == 0 || args[0] == "" { +		return ctx.StorageUserWebauthnListAllRunE(cmd, args) +	} + +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} @@ -272,13 +568,13 @@ func (ctx *CmdCtx) StorageWebauthnListRunE(cmd *cobra.Command, args []string) (e  	return nil  } -// StorageWebauthnListAllRunE is the RunE for the authelia storage user webauthn list command when no args are specified. -func (ctx *CmdCtx) StorageWebauthnListAllRunE(_ *cobra.Command, _ []string) (err error) { +// StorageUserWebauthnListAllRunE is the RunE for the authelia storage user webauthn list command when no args are specified. +func (ctx *CmdCtx) StorageUserWebauthnListAllRunE(_ *cobra.Command, _ []string) (err error) {  	defer func() {  		_ = ctx.providers.StorageProvider.Close()  	}() -	if err = ctx.CheckSchemaVersion(); err != nil { +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} @@ -312,13 +608,13 @@ func (ctx *CmdCtx) StorageWebauthnListAllRunE(_ *cobra.Command, _ []string) (err  	return nil  } -// StorageWebauthnDeleteRunE is the RunE for the authelia storage user webauthn delete command. -func (ctx *CmdCtx) StorageWebauthnDeleteRunE(cmd *cobra.Command, args []string) (err error) { +// StorageUserWebauthnDeleteRunE is the RunE for the authelia storage user webauthn delete command. +func (ctx *CmdCtx) StorageUserWebauthnDeleteRunE(cmd *cobra.Command, args []string) (err error) {  	defer func() {  		_ = ctx.providers.StorageProvider.Close()  	}() -	if err = ctx.CheckSchemaVersion(); err != nil { +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} @@ -333,33 +629,37 @@ func (ctx *CmdCtx) StorageWebauthnDeleteRunE(cmd *cobra.Command, args []string)  	if byKID {  		if err = ctx.providers.StorageProvider.DeleteWebauthnDevice(ctx, kid); err != nil { -			return fmt.Errorf("failed to delete WebAuthn device with kid '%s': %w", kid, err) +			return fmt.Errorf("failed to delete webauthn device with kid '%s': %w", kid, err)  		} -		fmt.Printf("Deleted WebAuthn device with kid '%s'", kid) +		fmt.Printf("Successfully deleted Webauthn device with key id '%s'\n", kid)  	} else {  		err = ctx.providers.StorageProvider.DeleteWebauthnDeviceByUsername(ctx, user, description)  		if all {  			if err != nil { -				return fmt.Errorf("failed to delete all WebAuthn devices with username '%s': %w", user, err) +				return fmt.Errorf("failed to delete all webauthn devices with username '%s': %w", user, err)  			} -			fmt.Printf("Deleted all WebAuthn devices for user '%s'", user) +			fmt.Printf("Successfully deleted all Webauthn devices for user '%s'\n", user)  		} else {  			if err != nil { -				return fmt.Errorf("failed to delete WebAuthn device with username '%s' and description '%s': %w", user, description, err) +				return fmt.Errorf("failed to delete webauthn device with username '%s' and description '%s': %w", user, description, err)  			} -			fmt.Printf("Deleted WebAuthn device with username '%s' and description '%s'", user, description) +			fmt.Printf("Successfully deleted Webauthn device with description '%s' for user '%s'\n", description, user)  		}  	}  	return nil  } -// StorageTOTPGenerateRunE is the RunE for the authelia storage user totp generate command. -func (ctx *CmdCtx) StorageTOTPGenerateRunE(cmd *cobra.Command, args []string) (err error) { +// StorageUserTOTPGenerateRunE is the RunE for the authelia storage user totp generate command. +func (ctx *CmdCtx) StorageUserTOTPGenerateRunE(cmd *cobra.Command, args []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() +  	var (  		c                *model.TOTPConfiguration  		force            bool @@ -368,11 +668,7 @@ func (ctx *CmdCtx) StorageTOTPGenerateRunE(cmd *cobra.Command, args []string) (e  		img              image.Image  	) -	defer func() { -		_ = ctx.providers.StorageProvider.Close() -	}() - -	if err = ctx.CheckSchemaVersion(); err != nil { +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} @@ -420,315 +716,357 @@ func (ctx *CmdCtx) StorageTOTPGenerateRunE(cmd *cobra.Command, args []string) (e  		return err  	} -	fmt.Printf("Generated TOTP configuration for user '%s' with URI '%s'%s\n", args[0], c.URI(), extraInfo) +	fmt.Printf("Successfully generated TOTP configuration for user '%s' with URI '%s'%s\n", args[0], c.URI(), extraInfo)  	return nil  } -// StorageTOTPDeleteRunE is the RunE for the authelia storage user totp delete command. -func (ctx *CmdCtx) StorageTOTPDeleteRunE(cmd *cobra.Command, args []string) (err error) { -	user := args[0] - +// StorageUserTOTPDeleteRunE is the RunE for the authelia storage user totp delete command. +func (ctx *CmdCtx) StorageUserTOTPDeleteRunE(cmd *cobra.Command, args []string) (err error) {  	defer func() {  		_ = ctx.providers.StorageProvider.Close()  	}() -	if err = ctx.CheckSchemaVersion(); err != nil { +	user := args[0] + +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	}  	if _, err = ctx.providers.StorageProvider.LoadTOTPConfiguration(ctx, user); err != nil { -		return fmt.Errorf("can't delete configuration for user '%s': %+v", user, err) +		return fmt.Errorf("failed to delete TOTP configuration for user '%s': %+v", user, err)  	}  	if err = ctx.providers.StorageProvider.DeleteTOTPConfiguration(ctx, user); err != nil { -		return fmt.Errorf("can't delete configuration for user '%s': %+v", user, err) +		return fmt.Errorf("failed to delete TOTP configuration for user '%s': %+v", user, err)  	} -	fmt.Printf("Deleted TOTP configuration for user '%s'.", user) +	fmt.Printf("Successfully deleted TOTP configuration for user '%s'\n", user)  	return nil  } -// StorageTOTPExportRunE is the RunE for the authelia storage user totp export command. -func (ctx *CmdCtx) StorageTOTPExportRunE(cmd *cobra.Command, args []string) (err error) { -	var ( -		format, dir    string -		configurations []model.TOTPConfiguration -		img            image.Image -	) +const ( +	cliOutputFmtSuccessfulUserExportFile = "Successfully exported %d %s as %s to the '%s' file\n" +	cliOutputFmtSuccessfulUserImportFile = "Successfully imported %d %s from the %s file '%s' into the database\n" +) +// StorageUserTOTPExportRunE is the RunE for the authelia storage user totp export command. +func (ctx *CmdCtx) StorageUserTOTPExportRunE(cmd *cobra.Command, _ []string) (err error) {  	defer func() {  		_ = ctx.providers.StorageProvider.Close()  	}() -	if err = ctx.CheckSchemaVersion(); err != nil { +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} -	if format, dir, err = flagsGetTOTPExportOptions(cmd.Flags()); err != nil { +	var ( +		filename string +	) + +	if filename, err = cmd.Flags().GetString(cmdFlagNameFile); err != nil {  		return err  	} +	switch _, err = os.Stat(filename); { +	case err == nil: +		return fmt.Errorf("must specify a file that doesn't exist but '%s' exists", filename) +	case !os.IsNotExist(err): +		return fmt.Errorf("error occurred opening '%s': %w", filename, err) +	} +  	limit := 10 +	count := 0 + +	var ( +		configs []model.TOTPConfiguration +	) + +	export := &model.TOTPConfigurationExport{}  	for page := 0; true; page++ { -		if configurations, err = ctx.providers.StorageProvider.LoadTOTPConfigurations(ctx, limit, page); err != nil { +		if configs, err = ctx.providers.StorageProvider.LoadTOTPConfigurations(ctx, limit, page); err != nil {  			return err  		} -		if page == 0 && format == storageTOTPExportFormatCSV { -			fmt.Printf("issuer,username,algorithm,digits,period,secret\n") -		} +		export.TOTPConfigurations = append(export.TOTPConfigurations, configs...) -		for _, c := range configurations { -			switch format { -			case storageTOTPExportFormatCSV: -				fmt.Printf("%s,%s,%s,%d,%d,%s\n", c.Issuer, c.Username, c.Algorithm, c.Digits, c.Period, string(c.Secret)) -			case storageTOTPExportFormatURI: -				fmt.Println(c.URI()) -			case storageTOTPExportFormatPNG: -				file, _ := os.Create(filepath.Join(dir, fmt.Sprintf("%s.png", c.Username))) +		l := len(configs) -				if img, err = c.Image(256, 256); err != nil { -					_ = file.Close() +		count += l -					return err -				} - -				if err = png.Encode(file, img); err != nil { -					_ = file.Close() - -					return err -				} - -				_ = file.Close() -			} -		} - -		if len(configurations) < limit { +		if l < limit {  			break  		}  	} -	if format == storageTOTPExportFormatPNG { -		fmt.Printf("Exported TOTP QR codes in PNG format in the '%s' directory\n", dir) +	var data []byte + +	if data, err = yaml.Marshal(export); err != nil { +		return fmt.Errorf("error occurred marshalling data to YAML: %w", err)  	} +	if err = os.WriteFile(filename, data, 0600); err != nil { +		return fmt.Errorf("error occurred writing to file '%s': %w", filename, err) +	} + +	fmt.Printf(cliOutputFmtSuccessfulUserExportFile, count, "TOTP configurations", "YAML", filename) +  	return nil  } -// StorageMigrateHistoryRunE is the RunE for the authelia storage migrate history command. -func (ctx *CmdCtx) StorageMigrateHistoryRunE(_ *cobra.Command, _ []string) (err error) { -	var ( -		version    int -		migrations []model.Migration -	) - +func (ctx *CmdCtx) StorageUserTOTPImportRunE(_ *cobra.Command, args []string) (err error) {  	defer func() {  		_ = ctx.providers.StorageProvider.Close()  	}() -	if version, err = ctx.providers.StorageProvider.SchemaVersion(ctx); err != nil { -		return err +	var ( +		filename string + +		stat os.FileInfo +		data []byte +	) + +	filename = args[0] + +	if stat, err = os.Stat(filename); err != nil { +		return fmt.Errorf("must specify a filename that exists but '%s' had an error opening it: %w", filename, err)  	} -	if version <= 0 { -		fmt.Println("No migration history is available for schemas that not version 1 or above.") -		return +	if stat.IsDir() { +		return fmt.Errorf("must specify a filename that exists but '%s' is a directory", filename)  	} -	if migrations, err = ctx.providers.StorageProvider.SchemaMigrationHistory(ctx); err != nil { +	if data, err = os.ReadFile(filename); err != nil {  		return err  	} -	if len(migrations) == 0 { -		return errors.New("no migration history found which may indicate a broken schema") +	export := &model.TOTPConfigurationExport{} + +	if err = yaml.Unmarshal(data, export); err != nil { +		return err  	} -	fmt.Printf("Migration History:\n\nID\tDate\t\t\t\tBefore\tAfter\tAuthelia Version\n") +	if len(export.TOTPConfigurations) == 0 { +		return fmt.Errorf("can't import a YAML file without TOTP configuration data") +	} -	for _, m := range migrations { -		fmt.Printf("%d\t%s\t%d\t%d\t%s\n", m.ID, m.Applied.Format("2006-01-02 15:04:05 -0700"), m.Before, m.After, m.Version) +	if err = ctx.CheckSchema(); err != nil { +		return storageWrapCheckSchemaErr(err) +	} + +	for _, config := range export.TOTPConfigurations { +		if err = ctx.providers.StorageProvider.SaveTOTPConfiguration(ctx, config); err != nil { +			return err +		}  	} +	fmt.Printf(cliOutputFmtSuccessfulUserImportFile, len(export.TOTPConfigurations), "TOTP configurations", "YAML", filename) +  	return nil  } -// NewStorageMigrateListRunE creates the RunE for the authelia storage migrate list command. -func (ctx *CmdCtx) NewStorageMigrateListRunE(up bool) func(cmd *cobra.Command, args []string) (err error) { -	return func(cmd *cobra.Command, args []string) (err error) { -		var ( -			migrations   []model.SchemaMigration -			directionStr string -		) +func (ctx *CmdCtx) StorageUserTOTPExportURIRunE(_ *cobra.Command, _ []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() -		defer func() { -			_ = ctx.providers.StorageProvider.Close() -		}() +	var ( +		configs []model.TOTPConfiguration +	) -		if up { -			migrations, err = ctx.providers.StorageProvider.SchemaMigrationsUp(ctx, 0) -			directionStr = "Up" -		} else { -			migrations, err = ctx.providers.StorageProvider.SchemaMigrationsDown(ctx, 0) -			directionStr = "Down" -		} +	if err = ctx.CheckSchema(); err != nil { +		return storageWrapCheckSchemaErr(err) +	} -		if err != nil && !errors.Is(err, storage.ErrNoAvailableMigrations) && !errors.Is(err, storage.ErrMigrateCurrentVersionSameAsTarget) { +	limit := 10 +	count := 0 + +	buf := &bytes.Buffer{} + +	for page := 0; true; page++ { +		if configs, err = ctx.providers.StorageProvider.LoadTOTPConfigurations(ctx, limit, page); err != nil {  			return err  		} -		if len(migrations) == 0 { -			fmt.Printf("Storage Schema Migration List (%s)\n\nNo Migrations Available\n", directionStr) -		} else { -			fmt.Printf("Storage Schema Migration List (%s)\n\nVersion\t\tDescription\n", directionStr) - -			for _, migration := range migrations { -				fmt.Printf("%d\t\t%s\n", migration.Version, migration.Name) -			} +		for _, c := range configs { +			buf.WriteString(fmt.Sprintf("%s\n", c.URI()))  		} -		return nil +		l := len(configs) + +		count += l + +		if l < limit { +			break +		}  	} + +	fmt.Print(buf.String()) + +	fmt.Printf("\n\nSuccessfully exported %d TOTP configurations as TOTP URI's and printed them to the console\n", count) + +	return nil  } -// NewStorageMigrationRunE creates the RunE for the authelia storage migrate command. -func (ctx *CmdCtx) NewStorageMigrationRunE(up bool) func(cmd *cobra.Command, args []string) (err error) { -	return func(cmd *cobra.Command, args []string) (err error) { -		var ( -			target int -		) +func (ctx *CmdCtx) StorageUserTOTPExportCSVRunE(cmd *cobra.Command, _ []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() -		defer func() { -			_ = ctx.providers.StorageProvider.Close() -		}() +	var ( +		filename string +		configs  []model.TOTPConfiguration +		buf      *bytes.Buffer +	) -		if target, err = cmd.Flags().GetInt(cmdFlagNameTarget); err != nil { +	if err = ctx.CheckSchema(); err != nil { +		return storageWrapCheckSchemaErr(err) +	} + +	if filename, err = cmd.Flags().GetString(cmdFlagNameFile); err != nil { +		return err +	} + +	limit := 10 +	count := 0 + +	buf = &bytes.Buffer{} + +	buf.WriteString("issuer,username,algorithm,digits,period,secret\n") + +	for page := 0; true; page++ { +		if configs, err = ctx.providers.StorageProvider.LoadTOTPConfigurations(ctx, limit, page); err != nil {  			return err  		} -		switch { -		case up: -			switch cmd.Flags().Changed(cmdFlagNameTarget) { -			case true: -				return ctx.providers.StorageProvider.SchemaMigrate(ctx, true, target) -			default: -				return ctx.providers.StorageProvider.SchemaMigrate(ctx, true, storage.SchemaLatest) -			} -		default: -			if !cmd.Flags().Changed(cmdFlagNameTarget) { -				return errors.New("you must set a target version") -			} - -			var confirmed bool +		for _, c := range configs { +			buf.WriteString(fmt.Sprintf("%s,%s,%s,%d,%d,%s\n", c.Issuer, c.Username, c.Algorithm, c.Digits, c.Period, string(c.Secret))) +		} -			if confirmed, err = termReadConfirmation(cmd.Flags(), cmdFlagNameDestroyData, "Schema Down Migrations may DESTROY data, type 'DESTROY' and press return to continue: ", "DESTROY"); err != nil { -				return err -			} +		l := len(configs) -			if !confirmed { -				return errors.New("cancelling down migration due to user not accepting data destruction") -			} +		count += l -			return ctx.providers.StorageProvider.SchemaMigrate(ctx, false, target) +		if l < limit { +			break  		}  	} -} -// StorageSchemaInfoRunE is the RunE for the authelia storage schema info command. -func (ctx *CmdCtx) StorageSchemaInfoRunE(_ *cobra.Command, _ []string) (err error) { -	var ( -		upgradeStr, tablesStr string +	if err = os.WriteFile(filename, buf.Bytes(), 0600); err != nil { +		return err +	} -		tables          []string -		version, latest int -	) +	fmt.Printf(cliOutputFmtSuccessfulUserExportFile, count, "TOTP configurations", "CSV", filename) + +	return nil +} +func (ctx *CmdCtx) StorageUserTOTPExportPNGRunE(cmd *cobra.Command, _ []string) (err error) {  	defer func() {  		_ = ctx.providers.StorageProvider.Close()  	}() -	if version, err = ctx.providers.StorageProvider.SchemaVersion(ctx); err != nil && err.Error() != "unknown schema state" { -		return err +	var ( +		dir     string +		configs []model.TOTPConfiguration +		img     image.Image +	) + +	if err = ctx.CheckSchema(); err != nil { +		return storageWrapCheckSchemaErr(err)  	} -	if tables, err = ctx.providers.StorageProvider.SchemaTables(ctx); err != nil { +	if dir, err = cmd.Flags().GetString(cmdFlagNameDirectory); err != nil {  		return err  	} -	if len(tables) == 0 { -		tablesStr = "N/A" -	} else { -		tablesStr = strings.Join(tables, ", ") +	if dir == "" { +		dir = utils.RandomString(8, utils.CharSetAlphaNumeric, false)  	} -	if latest, err = ctx.providers.StorageProvider.SchemaLatestVersion(); err != nil { -		return err +	if _, err = os.Stat(dir); !os.IsNotExist(err) { +		return errors.New("output directory must not exist")  	} -	if latest > version { -		upgradeStr = fmt.Sprintf("yes - version %d", latest) -	} else { -		upgradeStr = "no" +	if err = os.MkdirAll(dir, 0700); err != nil { +		return err  	} -	var ( -		encryption string -		result     storage.EncryptionValidationResult -	) +	limit := 10 +	count := 0 -	switch result, err = ctx.providers.StorageProvider.SchemaEncryptionCheckKey(ctx, false); { -	case err != nil: -		if errors.Is(err, storage.ErrSchemaEncryptionVersionUnsupported) { -			encryption = "unsupported (schema version)" -		} else { -			encryption = invalid +	var file *os.File + +	for page := 0; true; page++ { +		if configs, err = ctx.providers.StorageProvider.LoadTOTPConfigurations(ctx, limit, page); err != nil { +			return err +		} + +		for _, c := range configs { +			if file, err = os.Create(filepath.Join(dir, fmt.Sprintf("%s.png", c.Username))); err != nil { +				return err +			} + +			if img, err = c.Image(256, 256); err != nil { +				_ = file.Close() + +				return err +			} + +			if err = png.Encode(file, img); err != nil { +				_ = file.Close() + +				return err +			} + +			_ = file.Close() +		} + +		l := len(configs) + +		count += l + +		if l < limit { +			break  		} -	case !result.Success(): -		encryption = invalid -	default: -		encryption = "valid"  	} -	fmt.Printf("Schema Version: %s\nSchema Upgrade Available: %s\nSchema Tables: %s\nSchema Encryption Key: %s\n", storage.SchemaVersionToString(version), upgradeStr, tablesStr, encryption) +	fmt.Printf("Successfully exported %d TOTP configuration as QR codes in PNG format to the '%s' directory\n", count, dir)  	return nil  }  // StorageUserIdentifiersExportRunE is the RunE for the authelia storage user identifiers export command.  func (ctx *CmdCtx) StorageUserIdentifiersExportRunE(cmd *cobra.Command, _ []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() + +	if err = ctx.CheckSchema(); err != nil { +		return storageWrapCheckSchemaErr(err) +	} +  	var ( -		file string +		filename string  	) -	if file, err = cmd.Flags().GetString(cmdFlagNameFile); err != nil { +	if filename, err = cmd.Flags().GetString(cmdFlagNameFile); err != nil {  		return err  	} -	_, err = os.Stat(file) - -	switch { +	switch _, err = os.Stat(filename); {  	case err == nil: -		return fmt.Errorf("must specify a file that doesn't exist but '%s' exists", file) +		return fmt.Errorf("must specify a file that doesn't exist but '%s' exists", filename)  	case !os.IsNotExist(err): -		return fmt.Errorf("error occurred opening '%s': %w", file, err) +		return fmt.Errorf("error occurred opening '%s': %w", filename, err)  	} -	defer func() { -		_ = ctx.providers.StorageProvider.Close() -	}() - -	if err = ctx.CheckSchemaVersion(); err != nil { -		return storageWrapCheckSchemaErr(err) +	export := &model.UserOpaqueIdentifiersExport{ +		Identifiers: nil,  	} -	var ( -		export model.UserOpaqueIdentifiersExport - -		data []byte -	) -  	if export.Identifiers, err = ctx.providers.StorageProvider.LoadUserOpaqueIdentifiers(ctx); err != nil {  		return err  	} @@ -737,60 +1075,59 @@ func (ctx *CmdCtx) StorageUserIdentifiersExportRunE(cmd *cobra.Command, _ []stri  		return fmt.Errorf("no data to export")  	} -	if data, err = yaml.Marshal(&export); err != nil { +	var data []byte + +	if data, err = yaml.Marshal(export); err != nil {  		return fmt.Errorf("error occurred marshalling data to YAML: %w", err)  	} -	if err = os.WriteFile(file, data, 0600); err != nil { -		return fmt.Errorf("error occurred writing to file '%s': %w", file, err) +	if err = os.WriteFile(filename, data, 0600); err != nil { +		return fmt.Errorf("error occurred writing to file '%s': %w", filename, err)  	} -	fmt.Printf("Exported %d User Opaque Identifiers to %s\n", len(export.Identifiers), file) +	fmt.Printf(cliOutputFmtSuccessfulUserExportFile, len(export.Identifiers), "User Opaque Identifiers", "YAML", filename)  	return nil  }  // StorageUserIdentifiersImportRunE is the RunE for the authelia storage user identifiers import command. -func (ctx *CmdCtx) StorageUserIdentifiersImportRunE(cmd *cobra.Command, _ []string) (err error) { +func (ctx *CmdCtx) StorageUserIdentifiersImportRunE(cmd *cobra.Command, args []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() +  	var ( -		file string +		filename string +  		stat os.FileInfo +		data []byte  	) -	if file, err = cmd.Flags().GetString(cmdFlagNameFile); err != nil { -		return err -	} +	filename = args[0] -	if stat, err = os.Stat(file); err != nil { -		return fmt.Errorf("must specify a file that exists but '%s' had an error opening it: %w", file, err) +	if stat, err = os.Stat(filename); err != nil { +		return fmt.Errorf("must specify a file that exists but '%s' had an error opening it: %w", filename, err)  	}  	if stat.IsDir() { -		return fmt.Errorf("must specify a file that exists but '%s' is a directory", file) +		return fmt.Errorf("must specify a file that exists but '%s' is a directory", filename)  	} -	var ( -		data   []byte -		export model.UserOpaqueIdentifiersExport -	) - -	if data, err = os.ReadFile(file); err != nil { +	if data, err = os.ReadFile(filename); err != nil {  		return err  	} -	if err = yaml.Unmarshal(data, &export); err != nil { +	export := &model.UserOpaqueIdentifiersExport{} + +	if err = yaml.Unmarshal(data, export); err != nil {  		return err  	}  	if len(export.Identifiers) == 0 { -		return fmt.Errorf("can't import a file with no data") +		return fmt.Errorf("can't import a YAML file without User Opaque Identifiers data")  	} -	defer func() { -		_ = ctx.providers.StorageProvider.Close() -	}() - -	if err = ctx.CheckSchemaVersion(); err != nil { +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} @@ -800,22 +1137,22 @@ func (ctx *CmdCtx) StorageUserIdentifiersImportRunE(cmd *cobra.Command, _ []stri  		}  	} -	fmt.Printf("Imported User Opaque Identifiers from %s\n", file) +	fmt.Printf(cliOutputFmtSuccessfulUserImportFile, len(export.Identifiers), "User Opaque Identifiers", "YAML", filename)  	return nil  }  // StorageUserIdentifiersGenerateRunE is the RunE for the authelia storage user identifiers generate command.  func (ctx *CmdCtx) StorageUserIdentifiersGenerateRunE(cmd *cobra.Command, _ []string) (err error) { -	var ( -		users, services, sectors []string -	) -  	defer func() {  		_ = ctx.providers.StorageProvider.Close()  	}() -	if err = ctx.CheckSchemaVersion(); err != nil { +	var ( +		users, services, sectors []string +	) + +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} @@ -871,13 +1208,26 @@ func (ctx *CmdCtx) StorageUserIdentifiersGenerateRunE(cmd *cobra.Command, _ []st  		}  	} -	fmt.Printf("Successfully added %d opaque identifiers and %d duplicates were skipped\n", added, duplicates) +	fmt.Printf("Successfully generated and addded opaque identifiers:\n") +	fmt.Printf("\tUsers: '%s'\n", strings.Join(users, "', '")) +	fmt.Printf("\tSectors: '%s'\n", strings.Join(sectors, "', '")) +	fmt.Printf("\tServices: '%s'\n", strings.Join(services, "', '")) + +	if duplicates != 0 { +		fmt.Printf("\tSkipped Duplicates: %d\n", duplicates) +	} + +	fmt.Printf("\tTotal: %d", added)  	return nil  }  // StorageUserIdentifiersAddRunE is the RunE for the authelia storage user identifiers add command.  func (ctx *CmdCtx) StorageUserIdentifiersAddRunE(cmd *cobra.Command, args []string) (err error) { +	defer func() { +		_ = ctx.providers.StorageProvider.Close() +	}() +  	var (  		service, sector string  	) @@ -922,11 +1272,7 @@ func (ctx *CmdCtx) StorageUserIdentifiersAddRunE(cmd *cobra.Command, args []stri  		}  	} -	defer func() { -		_ = ctx.providers.StorageProvider.Close() -	}() - -	if err = ctx.CheckSchemaVersion(); err != nil { +	if err = ctx.CheckSchema(); err != nil {  		return storageWrapCheckSchemaErr(err)  	} diff --git a/internal/commands/util.go b/internal/commands/util.go index 8d1eb95d4..19072f9a4 100644 --- a/internal/commands/util.go +++ b/internal/commands/util.go @@ -46,37 +46,6 @@ func flagsGetUserIdentifiersGenerateOptions(flags *pflag.FlagSet) (users, servic  	return users, services, sectors, nil  } -func flagsGetTOTPExportOptions(flags *pflag.FlagSet) (format, dir string, err error) { -	if format, err = flags.GetString(cmdFlagNameFormat); err != nil { -		return "", "", err -	} - -	if dir, err = flags.GetString("dir"); err != nil { -		return "", "", err -	} - -	switch format { -	case storageTOTPExportFormatCSV, storageTOTPExportFormatURI: -		break -	case storageTOTPExportFormatPNG: -		if dir == "" { -			dir = utils.RandomString(8, utils.CharSetAlphaNumeric, 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 -} -  //nolint:gocyclo  func flagsGetRandomCharacters(flags *pflag.FlagSet, flagNameLength, flagNameCharSet, flagNameCharacters string) (r string, err error) {  	var ( diff --git a/internal/model/totp_configuration.go b/internal/model/totp_configuration.go index f8f23d41b..a262ddb7b 100644 --- a/internal/model/totp_configuration.go +++ b/internal/model/totp_configuration.go @@ -2,12 +2,14 @@ package model  import (  	"database/sql" +	"encoding/base64"  	"image"  	"net/url"  	"strconv"  	"time"  	"github.com/pquerna/otp" +	"gopkg.in/yaml.v3"  )  // TOTPConfiguration represents a users TOTP configuration row in the database. @@ -70,3 +72,62 @@ func (c *TOTPConfiguration) Image(width, height int) (img image.Image, err error  	return key.Image(width, height)  } + +// MarshalYAML marshals this model into YAML. +func (c *TOTPConfiguration) MarshalYAML() (any, error) { +	o := TOTPConfigurationData{ +		CreatedAt:  c.CreatedAt, +		LastUsedAt: c.LastUsed(), +		Username:   c.Username, +		Issuer:     c.Issuer, +		Algorithm:  c.Algorithm, +		Digits:     c.Digits, +		Period:     c.Period, +		Secret:     base64.StdEncoding.EncodeToString(c.Secret), +	} + +	return yaml.Marshal(o) +} + +// UnmarshalYAML unmarshalls YAML into this model. +func (c *TOTPConfiguration) UnmarshalYAML(value *yaml.Node) (err error) { +	o := &TOTPConfigurationData{} + +	if err = value.Decode(o); err != nil { +		return err +	} + +	if c.Secret, err = base64.StdEncoding.DecodeString(o.Secret); err != nil { +		return err +	} + +	c.CreatedAt = o.CreatedAt +	c.Username = o.Username +	c.Issuer = o.Issuer +	c.Algorithm = o.Algorithm +	c.Digits = o.Digits +	c.Period = o.Period + +	if o.LastUsedAt != nil { +		c.LastUsedAt = sql.NullTime{Valid: true, Time: *o.LastUsedAt} +	} + +	return nil +} + +// TOTPConfigurationData is used for marshalling/unmarshalling tasks. +type TOTPConfigurationData struct { +	CreatedAt  time.Time  `yaml:"created_at"` +	LastUsedAt *time.Time `yaml:"last_used_at"` +	Username   string     `yaml:"username"` +	Issuer     string     `yaml:"issuer"` +	Algorithm  string     `yaml:"algorithm"` +	Digits     uint       `yaml:"digits"` +	Period     uint       `yaml:"period"` +	Secret     string     `yaml:"secret"` +} + +// TOTPConfigurationExport represents a TOTPConfiguration export file. +type TOTPConfigurationExport struct { +	TOTPConfigurations []TOTPConfiguration `yaml:"totp_configurations"` +} diff --git a/internal/model/user_opaque_identifier.go b/internal/model/user_opaque_identifier.go index 557c1370d..43f7d2f6c 100644 --- a/internal/model/user_opaque_identifier.go +++ b/internal/model/user_opaque_identifier.go @@ -24,7 +24,7 @@ func NewUserOpaqueIdentifier(service, sectorID, username string) (id *UserOpaque  // UserOpaqueIdentifier represents an opaque identifier for a user. Commonly used with OAuth 2.0 and OpenID Connect.  type UserOpaqueIdentifier struct { -	ID       int    `db:"id" yaml:"id"` +	ID       int    `db:"id" yaml:"-"`  	Service  string `db:"service" yaml:"service"`  	SectorID string `db:"sector_id" yaml:"sector_id"`  	Username string `db:"username" yaml:"username"` diff --git a/internal/model/webauthn.go b/internal/model/webauthn.go index 415e50a69..a3a19c62e 100644 --- a/internal/model/webauthn.go +++ b/internal/model/webauthn.go @@ -2,6 +2,7 @@ package model  import (  	"database/sql" +	"encoding/base64"  	"encoding/hex"  	"strings"  	"time" @@ -9,6 +10,7 @@ import (  	"github.com/go-webauthn/webauthn/protocol"  	"github.com/go-webauthn/webauthn/webauthn"  	"github.com/google/uuid" +	"gopkg.in/yaml.v3"  )  const ( @@ -153,19 +155,114 @@ type WebauthnDevice struct {  }  // UpdateSignInInfo adjusts the values of the WebauthnDevice after a sign in. -func (w *WebauthnDevice) UpdateSignInInfo(config *webauthn.Config, now time.Time, signCount uint32) { -	w.LastUsedAt = sql.NullTime{Time: now, Valid: true} +func (d *WebauthnDevice) UpdateSignInInfo(config *webauthn.Config, now time.Time, signCount uint32) { +	d.LastUsedAt = sql.NullTime{Time: now, Valid: true} -	w.SignCount = signCount +	d.SignCount = signCount -	if w.RPID != "" { +	if d.RPID != "" {  		return  	} -	switch w.AttestationType { +	switch d.AttestationType {  	case attestationTypeFIDOU2F: -		w.RPID = config.RPOrigin +		d.RPID = config.RPOrigin  	default: -		w.RPID = config.RPID +		d.RPID = config.RPID  	}  } + +func (d *WebauthnDevice) LastUsed() *time.Time { +	if d.LastUsedAt.Valid { +		return &d.LastUsedAt.Time +	} + +	return nil +} + +// MarshalYAML marshals this model into YAML. +func (d *WebauthnDevice) MarshalYAML() (any, error) { +	o := WebauthnDeviceData{ +		CreatedAt:       d.CreatedAt, +		LastUsedAt:      d.LastUsed(), +		RPID:            d.RPID, +		Username:        d.Username, +		Description:     d.Description, +		KID:             d.KID.String(), +		PublicKey:       base64.StdEncoding.EncodeToString(d.PublicKey), +		AttestationType: d.AttestationType, +		Transport:       d.Transport, +		AAGUID:          d.AAGUID.UUID.String(), +		SignCount:       d.SignCount, +		CloneWarning:    d.CloneWarning, +	} + +	return yaml.Marshal(o) +} + +// UnmarshalYAML unmarshalls YAML into this model. +func (d *WebauthnDevice) UnmarshalYAML(value *yaml.Node) (err error) { +	o := &WebauthnDeviceData{} + +	if err = value.Decode(o); err != nil { +		return err +	} + +	if d.PublicKey, err = base64.StdEncoding.DecodeString(o.PublicKey); err != nil { +		return err +	} + +	var aaguid uuid.UUID + +	if aaguid, err = uuid.Parse(o.AAGUID); err != nil { +		return err +	} + +	if aaguid.ID() != 0 { +		d.AAGUID = uuid.NullUUID{Valid: true, UUID: aaguid} +	} + +	var kid []byte + +	if kid, err = base64.StdEncoding.DecodeString(o.KID); err != nil { +		return err +	} + +	d.KID = NewBase64(kid) + +	d.CreatedAt = o.CreatedAt +	d.RPID = o.RPID +	d.Username = o.Username +	d.Description = o.Description +	d.AttestationType = o.AttestationType +	d.Transport = o.Transport +	d.SignCount = o.SignCount +	d.CloneWarning = o.CloneWarning + +	if o.LastUsedAt != nil { +		d.LastUsedAt = sql.NullTime{Valid: true, Time: *o.LastUsedAt} +	} + +	return nil +} + +// WebauthnDeviceData represents a Webauthn Device in the database storage. +type WebauthnDeviceData struct { +	CreatedAt       time.Time  `yaml:"created_at"` +	LastUsedAt      *time.Time `yaml:"last_used_at"` +	RPID            string     `yaml:"rpid"` +	Username        string     `yaml:"username"` +	Description     string     `yaml:"description"` +	KID             string     `yaml:"kid"` +	PublicKey       string     `yaml:"public_key"` +	AttestationType string     `yaml:"attestation_type"` +	Transport       string     `yaml:"transport"` +	AAGUID          string     `yaml:"aaguid"` +	SignCount       uint32     `yaml:"sign_count"` +	CloneWarning    bool       `yaml:"clone_warning"` +} + +// WebauthnDeviceExport represents a WebauthnDevice export file. +type WebauthnDeviceExport struct { +	WebauthnDevices []WebauthnDevice `yaml:"webauthn_devices"` +} diff --git a/internal/suites/suite_cli_test.go b/internal/suites/suite_cli_test.go index 715d1fb1a..e68099aec 100644 --- a/internal/suites/suite_cli_test.go +++ b/internal/suites/suite_cli_test.go @@ -5,6 +5,7 @@ import (  	"context"  	"fmt"  	"os" +	"path/filepath"  	"regexp"  	"strconv"  	"testing" @@ -929,13 +930,17 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {  		fileInfo os.FileInfo  	) +	dir := s.T().TempDir() + +	qr := filepath.Join(dir, "qr.png") +  	for _, testCase := range testCases {  		if testCase.png { -			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"}) +			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", qr, "--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'") +			s.Assert().Contains(output, fmt.Sprintf(" and saved it as a PNG image at the path '%s'", qr)) -			fileInfo, err = os.Stat("/tmp/qr.png") +			fileInfo, err = os.Stat(qr)  			s.Assert().NoError(err)  			s.Require().NotNil(fileInfo)  			s.Assert().False(fileInfo.IsDir()) @@ -954,30 +959,41 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {  		expectedLines = append(expectedLines, config.URI())  	} -	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "--format=uri", "--config=/config/configuration.storage.yml"}) +	yml := filepath.Join(dir, "authelia.export.totp.yaml") +	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "--file", yml, "--config=/config/configuration.storage.yml"}) +	s.Assert().NoError(err) +	s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d TOTP configurations as YAML to the '%s' file\n", len(expectedLines), yml)) + +	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "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", "user", "totp", "export", "--format=csv", "--config=/config/configuration.storage.yml"}) +	csv := filepath.Join(dir, "authelia.export.totp.csv") +	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "csv", "--file", csv, "--config=/config/configuration.storage.yml"})  	s.Assert().NoError(err) +	s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d TOTP configurations as CSV to the '%s' file\n", len(expectedLines), csv)) + +	var data []byte +	data, err = os.ReadFile(csv) +	s.Assert().NoError(err) + +	content := string(data)  	for _, expectedLine := range expectedLinesCSV { -		s.Assert().Contains(output, expectedLine) +		s.Assert().Contains(content, expectedLine)  	} -	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "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") +	pngs := filepath.Join(dir, "png-qr-codes") -	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"}) +	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "png", "--directory", pngs, "--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") +	s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d TOTP configuration as QR codes in PNG format to the '%s' directory\n", len(expectedLines), pngs))  	for _, testCase := range testCases { -		fileInfo, err = os.Stat(fmt.Sprintf("/tmp/qr/%s.png", testCase.config.Username)) +		fileInfo, err = os.Stat(filepath.Join(pngs, fmt.Sprintf("%s.png", testCase.config.Username)))  		s.Assert().NoError(err)  		s.Require().NotNil(fileInfo) @@ -986,13 +1002,13 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {  		s.Assert().Greater(fileInfo.Size(), int64(1000))  	} -	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"}) +	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "generate", "test", "--period=30", "--algorithm=SHA1", "--digits=6", "--path", qr, "--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) TestStorage04ShouldManageUniqueID() { -	_ = os.Mkdir("/tmp/out", 0777) +	dir := s.T().TempDir()  	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") @@ -1014,13 +1030,14 @@ func (s *CLISuite) TestStorage04ShouldManageUniqueID() {  	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"}) +	out1 := filepath.Join(dir, "1.yml") +	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file", out1, "--config=/config/configuration.storage.yml"})  	s.Assert().NoError(err) -	s.Assert().Contains(output, "Exported 1 User Opaque Identifiers to /tmp/out/1.yml") +	s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d User Opaque Identifiers as YAML to the '%s' file\n", 1, out1)) -	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"}) +	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file", out1, "--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") +	s.Assert().Contains(output, fmt.Sprintf("Error: must specify a file that doesn't exist but '%s' exists", out1))  	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"})  	s.Assert().EqualError(err, "exit status 1") @@ -1046,7 +1063,7 @@ func (s *CLISuite) TestStorage04ShouldManageUniqueID() {  	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") +	data, err := os.ReadFile(out1)  	s.Assert().NoError(err)  	var export model.UserOpaqueIdentifiersExport @@ -1055,32 +1072,30 @@ func (s *CLISuite) TestStorage04ShouldManageUniqueID() {  	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)  	s.Assert().Equal("openid", export.Identifiers[0].Service) -	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"}) +	out2 := filepath.Join(dir, "2.yml") +	output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file", out2, "--config=/config/configuration.storage.yml"})  	s.Assert().NoError(err) -	s.Assert().Contains(output, "Exported 2 User Opaque Identifiers to /tmp/out/2.yml") +	s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d User Opaque Identifiers as YAML to the '%s' file\n", 2, out2))  	export = model.UserOpaqueIdentifiersExport{} -	data, err = os.ReadFile("/tmp/out/2.yml") +	data, err = os.ReadFile(out2)  	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)  	s.Assert().Equal("openid", export.Identifiers[0].Service) -	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)  | 
