From fcac438637c43f55e84e226be323119042580bf5 Mon Sep 17 00:00:00 2001 From: James Elliott Date: Mon, 27 Jun 2022 18:27:57 +1000 Subject: [PATCH] feat(commands): enhance crypto generation capabilities (#2842) This expands the functionality of the certificates and rsa commands and merges them into one command called cypto which can either use the cert or pair subcommands to generate certificates or key-pairs respectively. The rsa, ecdsa, and ed25519 subcommands exist for both the cert and pair commands. A new --ca-path argument for the cert subcommand allows Authelia to sign other certs with CA certs. Co-authored-by: Amir Zarrinkafsh --- .../en/configuration/miscellaneous/guides.md | 8 +- docs/content/en/reference/cli/_index.md | 2 +- .../en/reference/cli/authelia-gen/_index.md | 2 +- .../cli/authelia-gen/authelia-gen.md | 4 +- .../cli/authelia-gen/authelia-gen_all.md | 4 +- .../cli/authelia-gen/authelia-gen_code.md | 4 +- .../authelia-gen/authelia-gen_code_keys.md | 4 +- .../cli/authelia-gen/authelia-gen_docs.md | 4 +- .../cli/authelia-gen/authelia-gen_docs_cli.md | 4 +- .../authelia-gen/authelia-gen_docs_time.md | 2 +- .../reference/cli/authelia-scripts/_index.md | 2 +- .../cli/authelia-scripts/authelia-scripts.md | 4 +- .../authelia-scripts_bootstrap.md | 4 +- .../authelia-scripts_build.md | 4 +- .../authelia-scripts_certificates.md | 2 +- .../authelia-scripts_certificates_generate.md | 2 +- .../authelia-scripts/authelia-scripts_ci.md | 4 +- .../authelia-scripts_clean.md | 4 +- .../authelia-scripts_docker.md | 4 +- .../authelia-scripts_docker_build.md | 4 +- .../authelia-scripts_docker_push-manifest.md | 4 +- .../authelia-scripts_hash-password.md | 2 +- .../authelia-scripts/authelia-scripts_rsa.md | 2 +- .../authelia-scripts_rsa_generate.md | 2 +- .../authelia-scripts_serve.md | 4 +- .../authelia-scripts_suites.md | 4 +- .../authelia-scripts_suites_list.md | 4 +- .../authelia-scripts_suites_setup.md | 4 +- .../authelia-scripts_suites_teardown.md | 4 +- .../authelia-scripts_suites_test.md | 4 +- .../authelia-scripts_unittest.md | 4 +- .../authelia-scripts_xflags.md | 4 +- .../en/reference/cli/authelia/_index.md | 2 +- .../en/reference/cli/authelia/authelia.md | 11 +- .../cli/authelia/authelia_access-control.md | 4 +- .../authelia_access-control_check-policy.md | 6 +- .../cli/authelia/authelia_build-info.md | 4 +- .../cli/authelia/authelia_certificates.md | 43 -- .../authelia_certificates_generate.md | 59 -- .../reference/cli/authelia/authelia_crypto.md | 43 ++ .../authelia/authelia_crypto_certificate.md | 44 ++ .../authelia_crypto_certificate_ecdsa.md | 43 ++ ...helia_crypto_certificate_ecdsa_generate.md | 66 ++ ...thelia_crypto_certificate_ecdsa_request.md | 61 ++ .../authelia_crypto_certificate_ed25519.md | 43 ++ ...lia_crypto_certificate_ed25519_generate.md | 65 ++ ...elia_crypto_certificate_ed25519_request.md | 60 ++ .../authelia_crypto_certificate_rsa.md | 43 ++ ...uthelia_crypto_certificate_rsa_generate.md | 66 ++ ...authelia_crypto_certificate_rsa_request.md | 61 ++ .../cli/authelia/authelia_crypto_pair.md | 44 ++ .../authelia/authelia_crypto_pair_ecdsa.md | 46 ++ .../authelia_crypto_pair_ecdsa_generate.md | 50 ++ .../authelia/authelia_crypto_pair_ed25519.md | 46 ++ .../authelia_crypto_pair_ed25519_generate.md | 49 ++ .../cli/authelia/authelia_crypto_pair_rsa.md | 46 ++ .../authelia_crypto_pair_rsa_generate.md | 50 ++ .../cli/authelia/authelia_hash-password.md | 6 +- .../en/reference/cli/authelia/authelia_rsa.md | 42 -- .../cli/authelia/authelia_rsa_generate.md | 48 -- .../cli/authelia/authelia_storage.md | 4 +- .../authelia/authelia_storage_encryption.md | 4 +- .../authelia_storage_encryption_change-key.md | 4 +- .../authelia_storage_encryption_check.md | 4 +- .../cli/authelia/authelia_storage_migrate.md | 4 +- .../authelia/authelia_storage_migrate_down.md | 4 +- .../authelia_storage_migrate_history.md | 4 +- .../authelia_storage_migrate_list-down.md | 4 +- .../authelia_storage_migrate_list-up.md | 4 +- .../authelia/authelia_storage_migrate_up.md | 4 +- .../authelia/authelia_storage_schema-info.md | 4 +- .../cli/authelia/authelia_storage_user.md | 4 +- .../authelia_storage_user_identifiers.md | 4 +- .../authelia_storage_user_identifiers_add.md | 4 +- ...uthelia_storage_user_identifiers_export.md | 4 +- ...helia_storage_user_identifiers_generate.md | 4 +- ...uthelia_storage_user_identifiers_import.md | 4 +- .../authelia/authelia_storage_user_totp.md | 4 +- .../authelia_storage_user_totp_delete.md | 4 +- .../authelia_storage_user_totp_export.md | 4 +- .../authelia_storage_user_totp_generate.md | 4 +- .../cli/authelia/authelia_validate-config.md | 4 +- examples/compose/local/setup.sh | 2 +- internal/commands/certificates.go | 169 ----- internal/commands/const.go | 135 +++- internal/commands/crypto.go | 451 ++++++++++++++ internal/commands/crypto_helper.go | 426 +++++++++++++ internal/commands/root.go | 3 +- internal/commands/rsa.go | 110 ---- internal/oidc/keys.go | 8 +- internal/suites/suite_cli_test.go | 527 ++++++++++++++-- internal/suites/utils.go | 5 +- internal/utils/certificates.go | 253 -------- internal/utils/certificates_test.go | 169 ----- internal/utils/const.go | 30 + internal/utils/crypto.go | 582 ++++++++++++++++++ internal/utils/crypto_test.go | 538 ++++++++++++++++ internal/utils/rsa.go | 83 --- 98 files changed, 3685 insertions(+), 1159 deletions(-) delete mode 100644 docs/content/en/reference/cli/authelia/authelia_certificates.md delete mode 100644 docs/content/en/reference/cli/authelia/authelia_certificates_generate.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_pair.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa_generate.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519_generate.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa.md create mode 100644 docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa_generate.md delete mode 100644 docs/content/en/reference/cli/authelia/authelia_rsa.md delete mode 100644 docs/content/en/reference/cli/authelia/authelia_rsa_generate.md delete mode 100644 internal/commands/certificates.go create mode 100644 internal/commands/crypto.go create mode 100644 internal/commands/crypto_helper.go delete mode 100644 internal/commands/rsa.go delete mode 100644 internal/utils/certificates.go delete mode 100644 internal/utils/certificates_test.go create mode 100644 internal/utils/crypto.go create mode 100644 internal/utils/crypto_test.go delete mode 100644 internal/utils/rsa.go diff --git a/docs/content/en/configuration/miscellaneous/guides.md b/docs/content/en/configuration/miscellaneous/guides.md index 64b5a402..34311d11 100644 --- a/docs/content/en/configuration/miscellaneous/guides.md +++ b/docs/content/en/configuration/miscellaneous/guides.md @@ -42,11 +42,11 @@ openssl rsa -in private.pem -outform PEM -pubout -out public.pem The __Authelia__ docker container or CLI binary can be used to generate a RSA 4096 bit keypair: ```bash -docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia:latest authelia rsa generate --dir /keys +docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia:latest authelia crypto pair rsa generate --bits 4096 --directory /keys ``` ```bash -authelia rsa generate --dir /path/to/keys +authelia crypto pair rsa generate --directory /path/to/keys ``` ## Generating an RSA Self-Signed Certificate @@ -69,9 +69,9 @@ The __Authelia__ docker container or binary can be used to generate a RSA 4096 b domain `example.com`: ```bash -docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia authelia certificates generate --host example.com --dir /keys +docker run -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia authelia crypto certificate rsa generate --common-name example.com --directory /keys ``` ```bash -authelia certificates generate --host example.com --dir /path/to/keys +authelia crypto certificate rsa generate --common-name example.com --directory /path/to/keys ``` diff --git a/docs/content/en/reference/cli/_index.md b/docs/content/en/reference/cli/_index.md index 6cbd0a1e..c6b867dd 100644 --- a/docs/content/en/reference/cli/_index.md +++ b/docs/content/en/reference/cli/_index.md @@ -2,7 +2,7 @@ title: "CLI" description: "" lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] weight: 300 diff --git a/docs/content/en/reference/cli/authelia-gen/_index.md b/docs/content/en/reference/cli/authelia-gen/_index.md index 02b76dde..3795ca9f 100644 --- a/docs/content/en/reference/cli/authelia-gen/_index.md +++ b/docs/content/en/reference/cli/authelia-gen/_index.md @@ -2,7 +2,7 @@ title: "authelia-gen" description: "" lead: "" -date: 2022-06-03T10:57:43+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen.md index 9f67ef67..69eab9aa 100644 --- a/docs/content/en/reference/cli/authelia-gen/authelia-gen.md +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen.md @@ -2,7 +2,7 @@ title: "authelia-gen" description: "Reference for the authelia-gen command." lead: "" -date: 2022-06-03T10:57:43+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -28,4 +28,4 @@ Authelia's generator tooling * [authelia-gen code](authelia-gen_code.md) - Generate code * [authelia-gen docs](authelia-gen_docs.md) - Generate docs -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_all.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_all.md index 8af83063..82101c37 100644 --- a/docs/content/en/reference/cli/authelia-gen/authelia-gen_all.md +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_all.md @@ -2,7 +2,7 @@ title: "authelia-gen all" description: "Reference for the authelia-gen all command." lead: "" -date: 2022-06-03T10:57:43+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -30,4 +30,4 @@ authelia-gen all [flags] * [authelia-gen](authelia-gen.md) - Authelia's generator tooling -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_code.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_code.md index b065e614..7445e9f8 100644 --- a/docs/content/en/reference/cli/authelia-gen/authelia-gen_code.md +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_code.md @@ -2,7 +2,7 @@ title: "authelia-gen code" description: "Reference for the authelia-gen code command." lead: "" -date: 2022-06-03T10:57:43+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -31,4 +31,4 @@ authelia-gen code [flags] * [authelia-gen](authelia-gen.md) - Authelia's generator tooling * [authelia-gen code keys](authelia-gen_code_keys.md) - Generate the list of valid configuration keys -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_code_keys.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_code_keys.md index 59b40514..725ac1ca 100644 --- a/docs/content/en/reference/cli/authelia-gen/authelia-gen_code_keys.md +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_code_keys.md @@ -2,7 +2,7 @@ title: "authelia-gen code keys" description: "Reference for the authelia-gen code keys command." lead: "" -date: 2022-06-03T10:57:43+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -32,4 +32,4 @@ authelia-gen code keys [flags] * [authelia-gen code](authelia-gen_code.md) - Generate code -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs.md index 470c325e..04a621f0 100644 --- a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs.md +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs.md @@ -2,7 +2,7 @@ title: "authelia-gen docs" description: "Reference for the authelia-gen docs command." lead: "" -date: 2022-06-03T10:57:43+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -33,4 +33,4 @@ authelia-gen docs [flags] * [authelia-gen docs cli](authelia-gen_docs_cli.md) - Generate CLI docs * [authelia-gen docs date](authelia-gen_docs_date.md) - Generate doc dates -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_cli.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_cli.md index f9f82f88..debd4e60 100644 --- a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_cli.md +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_cli.md @@ -2,7 +2,7 @@ title: "authelia-gen docs cli" description: "Reference for the authelia-gen docs cli command." lead: "" -date: 2022-06-03T10:57:43+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -37,4 +37,4 @@ authelia-gen docs cli [flags] * [authelia-gen docs](authelia-gen_docs.md) - Generate docs -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_time.md b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_time.md index f9fd4392..25402c2e 100644 --- a/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_time.md +++ b/docs/content/en/reference/cli/authelia-gen/authelia-gen_docs_time.md @@ -2,7 +2,7 @@ title: "authelia-gen docs time" description: "Reference for the authelia-gen docs time command." lead: "" -date: 2022-06-03T11:17:29+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: diff --git a/docs/content/en/reference/cli/authelia-scripts/_index.md b/docs/content/en/reference/cli/authelia-scripts/_index.md index d5900fab..b18caa9b 100644 --- a/docs/content/en/reference/cli/authelia-scripts/_index.md +++ b/docs/content/en/reference/cli/authelia-scripts/_index.md @@ -2,7 +2,7 @@ title: "authelia-scripts" description: "" lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts.md index 1ca48902..4ed27faa 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts.md @@ -2,7 +2,7 @@ title: "authelia-scripts" description: "Reference for the authelia-scripts command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -49,4 +49,4 @@ authelia-scripts help * [authelia-scripts unittest](authelia-scripts_unittest.md) - Run unit tests * [authelia-scripts xflags](authelia-scripts_xflags.md) - Generate X LDFlags for building Authelia -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_bootstrap.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_bootstrap.md index f06f7d77..f765e1a7 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_bootstrap.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_bootstrap.md @@ -2,7 +2,7 @@ title: "authelia-scripts bootstrap" description: "Reference for the authelia-scripts bootstrap command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -47,4 +47,4 @@ authelia-scripts bootstrap * [authelia-scripts](authelia-scripts.md) - A utility used in the Authelia development process. -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_build.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_build.md index 959f7c64..506090bd 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_build.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_build.md @@ -2,7 +2,7 @@ title: "authelia-scripts build" description: "Reference for the authelia-scripts build command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -47,4 +47,4 @@ authelia-scripts build * [authelia-scripts](authelia-scripts.md) - A utility used in the Authelia development process. -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates.md index 5179e329..62a98ca2 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates.md @@ -2,7 +2,7 @@ title: "authelia-scripts certificates" description: "Reference for the authelia-scripts certificates command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 lastmod: 2022-06-03T11:17:29+10:00 draft: false images: [] diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates_generate.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates_generate.md index 462cb2d8..685f7c1a 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates_generate.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_certificates_generate.md @@ -2,7 +2,7 @@ title: "authelia-scripts certificates generate" description: "Reference for the authelia-scripts certificates generate command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 lastmod: 2022-06-03T11:17:29+10:00 draft: false images: [] diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_ci.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_ci.md index 2ff57852..175b321b 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_ci.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_ci.md @@ -2,7 +2,7 @@ title: "authelia-scripts ci" description: "Reference for the authelia-scripts ci command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -47,4 +47,4 @@ authelia-scripts ci * [authelia-scripts](authelia-scripts.md) - A utility used in the Authelia development process. -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_clean.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_clean.md index 00bf92dc..43c97561 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_clean.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_clean.md @@ -2,7 +2,7 @@ title: "authelia-scripts clean" description: "Reference for the authelia-scripts clean command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -47,4 +47,4 @@ authelia-scripts clean * [authelia-scripts](authelia-scripts.md) - A utility used in the Authelia development process. -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker.md index 864c0afc..3f48251c 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker.md @@ -2,7 +2,7 @@ title: "authelia-scripts docker" description: "Reference for the authelia-scripts docker command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -49,4 +49,4 @@ authelia-scripts docker * [authelia-scripts docker build](authelia-scripts_docker_build.md) - Build the docker image of Authelia * [authelia-scripts docker push-manifest](authelia-scripts_docker_push-manifest.md) - Push Authelia docker manifest to the Docker registries -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_build.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_build.md index 79679788..f60f066a 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_build.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_build.md @@ -2,7 +2,7 @@ title: "authelia-scripts docker build" description: "Reference for the authelia-scripts docker build command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -48,4 +48,4 @@ authelia-scripts docker build * [authelia-scripts docker](authelia-scripts_docker.md) - Commands related to building and publishing docker image -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_push-manifest.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_push-manifest.md index 91c820af..64a576b2 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_push-manifest.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_docker_push-manifest.md @@ -2,7 +2,7 @@ title: "authelia-scripts docker push-manifest" description: "Reference for the authelia-scripts docker push-manifest command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -47,4 +47,4 @@ authelia-scripts docker push-manifest * [authelia-scripts docker](authelia-scripts_docker.md) - Commands related to building and publishing docker image -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_hash-password.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_hash-password.md index 8fc11527..c8236e2c 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_hash-password.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_hash-password.md @@ -2,7 +2,7 @@ title: "authelia-scripts hash-password" description: "Reference for the authelia-scripts hash-password command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 lastmod: 2022-06-03T11:17:29+10:00 draft: false images: [] diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa.md index e12a7c54..80196b3f 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa.md @@ -2,7 +2,7 @@ title: "authelia-scripts rsa" description: "Reference for the authelia-scripts rsa command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 lastmod: 2022-06-03T11:17:29+10:00 draft: false images: [] diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa_generate.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa_generate.md index 353b7a1a..8707c1c6 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa_generate.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_rsa_generate.md @@ -2,7 +2,7 @@ title: "authelia-scripts rsa generate" description: "Reference for the authelia-scripts rsa generate command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 lastmod: 2022-06-03T11:17:29+10:00 draft: false images: [] diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_serve.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_serve.md index b7a4b68e..b39dd395 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_serve.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_serve.md @@ -2,7 +2,7 @@ title: "authelia-scripts serve" description: "Reference for the authelia-scripts serve command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -47,4 +47,4 @@ authelia-scripts serve test.yml * [authelia-scripts](authelia-scripts.md) - A utility used in the Authelia development process. -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites.md index b95dbbc6..c4ef4938 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites.md @@ -2,7 +2,7 @@ title: "authelia-scripts suites" description: "Reference for the authelia-scripts suites command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -51,4 +51,4 @@ authelia-scripts suites * [authelia-scripts suites teardown](authelia-scripts_suites_teardown.md) - Teardown a test suite environment * [authelia-scripts suites test](authelia-scripts_suites_test.md) - Run a test suite -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_list.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_list.md index 6f6890c2..0dc98d8c 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_list.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_list.md @@ -2,7 +2,7 @@ title: "authelia-scripts suites list" description: "Reference for the authelia-scripts suites list command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -49,4 +49,4 @@ authelia-scripts suites list * [authelia-scripts suites](authelia-scripts_suites.md) - Commands related to suites management -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_setup.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_setup.md index cd18eb48..3fa26216 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_setup.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_setup.md @@ -2,7 +2,7 @@ title: "authelia-scripts suites setup" description: "Reference for the authelia-scripts suites setup command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -49,4 +49,4 @@ authelia-scripts suites setup Standalone * [authelia-scripts suites](authelia-scripts_suites.md) - Commands related to suites management -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_teardown.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_teardown.md index 684c353c..8e1c7213 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_teardown.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_teardown.md @@ -2,7 +2,7 @@ title: "authelia-scripts suites teardown" description: "Reference for the authelia-scripts suites teardown command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -49,4 +49,4 @@ authelia-scripts suites setup Standalone * [authelia-scripts suites](authelia-scripts_suites.md) - Commands related to suites management -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_test.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_test.md index 40107937..fdcbd6f3 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_test.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_suites_test.md @@ -2,7 +2,7 @@ title: "authelia-scripts suites test" description: "Reference for the authelia-scripts suites test command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -52,4 +52,4 @@ authelia-scripts suites test Standalone * [authelia-scripts suites](authelia-scripts_suites.md) - Commands related to suites management -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_unittest.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_unittest.md index cab5550d..a0a99bcd 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_unittest.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_unittest.md @@ -2,7 +2,7 @@ title: "authelia-scripts unittest" description: "Reference for the authelia-scripts unittest command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -47,4 +47,4 @@ authelia-scripts unittest * [authelia-scripts](authelia-scripts.md) - A utility used in the Authelia development process. -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_xflags.md b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_xflags.md index faa84356..ef16df7a 100644 --- a/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_xflags.md +++ b/docs/content/en/reference/cli/authelia-scripts/authelia-scripts_xflags.md @@ -2,7 +2,7 @@ title: "authelia-scripts xflags" description: "Reference for the authelia-scripts xflags command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -49,4 +49,4 @@ authelia-scripts xflags * [authelia-scripts](authelia-scripts.md) - A utility used in the Authelia development process. -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/_index.md b/docs/content/en/reference/cli/authelia/_index.md index 012ba993..aab5ea42 100644 --- a/docs/content/en/reference/cli/authelia/_index.md +++ b/docs/content/en/reference/cli/authelia/_index.md @@ -2,7 +2,7 @@ title: "authelia" description: "" lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: diff --git a/docs/content/en/reference/cli/authelia/authelia.md b/docs/content/en/reference/cli/authelia/authelia.md index 5bfeff7b..d9f727d8 100644 --- a/docs/content/en/reference/cli/authelia/authelia.md +++ b/docs/content/en/reference/cli/authelia/authelia.md @@ -2,7 +2,7 @@ title: "authelia" description: "Reference for the authelia command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -24,7 +24,7 @@ An open-source authentication and authorization server providing two-factor authentication and single sign-on (SSO) for your applications via a web portal. -Documentation is available at: https://www.authelia.com/docs +Documentation is available at: https://www.authelia.com/ ``` authelia [flags] @@ -49,10 +49,9 @@ authelia --config /etc/authelia/config/ * [authelia access-control](authelia_access-control.md) - Helpers for the access control system * [authelia build-info](authelia_build-info.md) - Show the build information of Authelia -* [authelia certificates](authelia_certificates.md) - Commands related to certificate generation -* [authelia hash-password](authelia_hash-password.md) - Hash a password to be used in file-based users database. -* [authelia rsa](authelia_rsa.md) - Commands related to rsa keypair generation +* [authelia crypto](authelia_crypto.md) - Perform cryptographic operations +* [authelia hash-password](authelia_hash-password.md) - Hash a password to be used in file-based users database * [authelia storage](authelia_storage.md) - Manage the Authelia storage * [authelia validate-config](authelia_validate-config.md) - Check a configuration against the internal configuration validation mechanisms -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 d525b658..8a642248 100644 --- a/docs/content/en/reference/cli/authelia/authelia_access-control.md +++ b/docs/content/en/reference/cli/authelia/authelia_access-control.md @@ -2,7 +2,7 @@ title: "authelia access-control" description: "Reference for the authelia access-control command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -37,4 +37,4 @@ authelia access-control --help * [authelia](authelia.md) - authelia untagged-unknown-dirty (master, unknown) * [authelia access-control check-policy](authelia_access-control_check-policy.md) - Checks a request against the access control rules to determine what policy would be applied -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 fbfba5fe..622134ab 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 @@ -2,7 +2,7 @@ title: "authelia access-control check-policy" description: "Reference for the authelia access-control check-policy command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -53,7 +53,7 @@ authelia access-control check-policy --config config.yml --url https://example.c ### Options ``` - -c, --config strings configuration files to load (default [config.yml]) + -c, --config strings configuration files to load (default [configuration.yml]) --groups strings the groups of the subject -h, --help help for check-policy --ip string the ip of the subject @@ -67,4 +67,4 @@ authelia access-control check-policy --config config.yml --url https://example.c * [authelia access-control](authelia_access-control.md) - Helpers for the access control system -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 20c17b54..9af59617 100644 --- a/docs/content/en/reference/cli/authelia/authelia_build-info.md +++ b/docs/content/en/reference/cli/authelia/authelia_build-info.md @@ -2,7 +2,7 @@ title: "authelia build-info" description: "Reference for the authelia build-info command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -49,4 +49,4 @@ authelia build-info * [authelia](authelia.md) - authelia untagged-unknown-dirty (master, unknown) -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_certificates.md b/docs/content/en/reference/cli/authelia/authelia_certificates.md deleted file mode 100644 index 8583c53f..00000000 --- a/docs/content/en/reference/cli/authelia/authelia_certificates.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "authelia certificates" -description: "Reference for the authelia certificates command." -lead: "" -date: 2022-05-31T11:13:56+10:00 -draft: false -images: [] -menu: - reference: - parent: "cli-authelia" -weight: 330 -toc: true ---- - -## authelia certificates - -Commands related to certificate generation - -### Synopsis - -Commands related to certificate generation. - -This subcommand allows preforming X509 certificate tasks. - -### Examples - -``` -authelia certificates --help -``` - -### Options - -``` - -h, --help help for certificates - --host strings Comma-separated hostnames and IPs to generate a certificate for -``` - -### SEE ALSO - -* [authelia](authelia.md) - authelia untagged-unknown-dirty (master, unknown) -* [authelia certificates generate](authelia_certificates_generate.md) - Generate a self-signed certificate - -###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_certificates_generate.md b/docs/content/en/reference/cli/authelia/authelia_certificates_generate.md deleted file mode 100644 index 672549c5..00000000 --- a/docs/content/en/reference/cli/authelia/authelia_certificates_generate.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: "authelia certificates generate" -description: "Reference for the authelia certificates generate command." -lead: "" -date: 2022-05-31T11:13:56+10:00 -draft: false -images: [] -menu: - reference: - parent: "cli-authelia" -weight: 330 -toc: true ---- - -## authelia certificates generate - -Generate a self-signed certificate - -### Synopsis - -Generate a self-signed certificate. - -This subcommand allows generating self-signed certificates. - -``` -authelia certificates generate [flags] -``` - -### Examples - -``` -authelia certificates generate -authelia certificates generate --dir ./out -``` - -### Options - -``` - --ca Whether this cert should be its own Certificate Authority - --dir string Target directory where the certificate and keys will be stored - --duration duration Duration that certificate is valid for (default 8760h0m0s) - --ecdsa-curve string ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521 - --ed25519 Generate an Ed25519 key - -h, --help help for generate - --rsa-bits int Size of RSA key to generate. Ignored if --ecdsa-curve is set (default 2048) - --start-date string Creation date formatted as Jan 1 15:04:05 2011 -``` - -### Options inherited from parent commands - -``` - --host strings Comma-separated hostnames and IPs to generate a certificate for -``` - -### SEE ALSO - -* [authelia certificates](authelia_certificates.md) - Commands related to certificate generation - -###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto.md b/docs/content/en/reference/cli/authelia/authelia_crypto.md new file mode 100644 index 00000000..cb61ce8a --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto.md @@ -0,0 +1,43 @@ +--- +title: "authelia crypto" +description: "Reference for the authelia crypto command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto + +Perform cryptographic operations + +### Synopsis + +Perform cryptographic operations. + +This subcommand allows preforming cryptographic certificate, key pair, etc tasks. + +### Examples + +``` +authelia crypto --help +``` + +### Options + +``` + -h, --help help for crypto +``` + +### SEE ALSO + +* [authelia](authelia.md) - authelia untagged-unknown-dirty (master, unknown) +* [authelia crypto certificate](authelia_crypto_certificate.md) - Perform certificate cryptographic operations +* [authelia crypto pair](authelia_crypto_pair.md) - Perform key pair cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate.md new file mode 100644 index 00000000..66fbf3fb --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate.md @@ -0,0 +1,44 @@ +--- +title: "authelia crypto certificate" +description: "Reference for the authelia crypto certificate command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate + +Perform certificate cryptographic operations + +### Synopsis + +Perform certificate cryptographic operations. + +This subcommand allows preforming certificate cryptographic tasks. + +### Examples + +``` +authelia crypto certificate --help +``` + +### Options + +``` + -h, --help help for certificate +``` + +### SEE ALSO + +* [authelia crypto](authelia_crypto.md) - Perform cryptographic operations +* [authelia crypto certificate ecdsa](authelia_crypto_certificate_ecdsa.md) - Perform ECDSA certificate cryptographic operations +* [authelia crypto certificate ed25519](authelia_crypto_certificate_ed25519.md) - Perform Ed25519 certificate cryptographic operations +* [authelia crypto certificate rsa](authelia_crypto_certificate_rsa.md) - Perform RSA certificate cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..6e0d9208 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa.md @@ -0,0 +1,43 @@ +--- +title: "authelia crypto certificate ecdsa" +description: "Reference for the authelia crypto certificate ecdsa command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate ecdsa + +Perform ECDSA certificate cryptographic operations + +### Synopsis + +Perform ECDSA certificate cryptographic operations. + +This subcommand allows preforming ECDSA certificate cryptographic tasks. + +### Examples + +``` +authelia crypto certificate ecdsa --help +``` + +### Options + +``` + -h, --help help for ecdsa +``` + +### SEE ALSO + +* [authelia crypto certificate](authelia_crypto_certificate.md) - Perform certificate cryptographic operations +* [authelia crypto certificate ecdsa generate](authelia_crypto_certificate_ecdsa_generate.md) - Generate an ECDSA private key and certificate +* [authelia crypto certificate ecdsa request](authelia_crypto_certificate_ecdsa_request.md) - Generate an ECDSA private key and certificate signing request + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..dcbe9872 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md @@ -0,0 +1,66 @@ +--- +title: "authelia crypto certificate ecdsa generate" +description: "Reference for the authelia crypto certificate ecdsa generate command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate ecdsa generate + +Generate an ECDSA private key and certificate + +### Synopsis + +Generate an ECDSA private key and certificate. + +This subcommand allows generating an ECDSA private key and certificate. + +``` +authelia crypto certificate ecdsa generate [flags] +``` + +### Examples + +``` +authelia crypto certificate ecdsa generate --help +``` + +### Options + +``` + --ca create the certificate as a certificate authority certificate + -c, --common-name string certificate common name + --country strings certificate country + -b, --curve string Sets the elliptic curve which can be P224, P256, P384, or P521 (default "P256") + -d, --directory string directory where the generated keys, certificates, etc will be stored + --duration duration duration of time the certificate is valid for (default 8760h0m0s) + --extended-usage strings specify the extended usage types of the certificate + --file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt") + --file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem") + --file.certificate string name of the file to export the certificate data to (default "public.crt") + --file.private-key string name of the file to export the private key data to (default "private.pem") + -h, --help help for generate + -l, --locality strings certificate locality + --not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now) + -o, --organization strings certificate organization (default [Authelia]) + --organizational-unit strings certificate organizational unit + --path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed + -p, --postcode strings certificate postcode + --province strings certificate province + --sans strings subject alternative names + --signature string signature algorithm for the certificate (default "SHA256") + -s, --street-address strings certificate street address +``` + +### SEE ALSO + +* [authelia crypto certificate ecdsa](authelia_crypto_certificate_ecdsa.md) - Perform ECDSA certificate cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..81889a92 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md @@ -0,0 +1,61 @@ +--- +title: "authelia crypto certificate ecdsa request" +description: "Reference for the authelia crypto certificate ecdsa request command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate ecdsa request + +Generate an ECDSA private key and certificate signing request + +### Synopsis + +Generate an ECDSA private key and certificate signing request. + +This subcommand allows generating an ECDSA private key and certificate signing request. + +``` +authelia crypto certificate ecdsa request [flags] +``` + +### Examples + +``` +authelia crypto certificate ecdsa request --help +``` + +### Options + +``` + -c, --common-name string certificate common name + --country strings certificate country + -b, --curve string Sets the elliptic curve which can be P224, P256, P384, or P521 (default "P256") + -d, --directory string directory where the generated keys, certificates, etc will be stored + --duration duration duration of time the certificate is valid for (default 8760h0m0s) + --file.csr string name of the file to export the certificate request data to (default "request.csr") + --file.private-key string name of the file to export the private key data to (default "private.pem") + -h, --help help for request + -l, --locality strings certificate locality + --not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now) + -o, --organization strings certificate organization (default [Authelia]) + --organizational-unit strings certificate organizational unit + -p, --postcode strings certificate postcode + --province strings certificate province + --sans strings subject alternative names + --signature string signature algorithm for the certificate (default "SHA256") + -s, --street-address strings certificate street address +``` + +### SEE ALSO + +* [authelia crypto certificate ecdsa](authelia_crypto_certificate_ecdsa.md) - Perform ECDSA certificate cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..8dced8f3 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519.md @@ -0,0 +1,43 @@ +--- +title: "authelia crypto certificate ed25519" +description: "Reference for the authelia crypto certificate ed25519 command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate ed25519 + +Perform Ed25519 certificate cryptographic operations + +### Synopsis + +Perform Ed25519 certificate cryptographic operations. + +This subcommand allows preforming Ed25519 certificate cryptographic tasks. + +### Examples + +``` +authelia crypto certificate ed25519 --help +``` + +### Options + +``` + -h, --help help for ed25519 +``` + +### SEE ALSO + +* [authelia crypto certificate](authelia_crypto_certificate.md) - Perform certificate cryptographic operations +* [authelia crypto certificate ed25519 generate](authelia_crypto_certificate_ed25519_generate.md) - Generate an Ed25519 private key and certificate +* [authelia crypto certificate ed25519 request](authelia_crypto_certificate_ed25519_request.md) - Generate an Ed25519 private key and certificate signing request + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..56dc593f --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md @@ -0,0 +1,65 @@ +--- +title: "authelia crypto certificate ed25519 generate" +description: "Reference for the authelia crypto certificate ed25519 generate command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate ed25519 generate + +Generate an Ed25519 private key and certificate + +### Synopsis + +Generate an Ed25519 private key and certificate. + +This subcommand allows generating an Ed25519 private key and certificate. + +``` +authelia crypto certificate ed25519 generate [flags] +``` + +### Examples + +``` +authelia crypto certificate ed25519 request --help +``` + +### Options + +``` + --ca create the certificate as a certificate authority certificate + -c, --common-name string certificate common name + --country strings certificate country + -d, --directory string directory where the generated keys, certificates, etc will be stored + --duration duration duration of time the certificate is valid for (default 8760h0m0s) + --extended-usage strings specify the extended usage types of the certificate + --file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt") + --file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem") + --file.certificate string name of the file to export the certificate data to (default "public.crt") + --file.private-key string name of the file to export the private key data to (default "private.pem") + -h, --help help for generate + -l, --locality strings certificate locality + --not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now) + -o, --organization strings certificate organization (default [Authelia]) + --organizational-unit strings certificate organizational unit + --path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed + -p, --postcode strings certificate postcode + --province strings certificate province + --sans strings subject alternative names + --signature string signature algorithm for the certificate (default "SHA256") + -s, --street-address strings certificate street address +``` + +### SEE ALSO + +* [authelia crypto certificate ed25519](authelia_crypto_certificate_ed25519.md) - Perform Ed25519 certificate cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..5dea9ada --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md @@ -0,0 +1,60 @@ +--- +title: "authelia crypto certificate ed25519 request" +description: "Reference for the authelia crypto certificate ed25519 request command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate ed25519 request + +Generate an Ed25519 private key and certificate signing request + +### Synopsis + +Generate an Ed25519 private key and certificate signing request. + +This subcommand allows generating an Ed25519 private key and certificate signing request. + +``` +authelia crypto certificate ed25519 request [flags] +``` + +### Examples + +``` +authelia crypto certificate ed25519 request --help +``` + +### Options + +``` + -c, --common-name string certificate common name + --country strings certificate country + -d, --directory string directory where the generated keys, certificates, etc will be stored + --duration duration duration of time the certificate is valid for (default 8760h0m0s) + --file.csr string name of the file to export the certificate request data to (default "request.csr") + --file.private-key string name of the file to export the private key data to (default "private.pem") + -h, --help help for request + -l, --locality strings certificate locality + --not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now) + -o, --organization strings certificate organization (default [Authelia]) + --organizational-unit strings certificate organizational unit + -p, --postcode strings certificate postcode + --province strings certificate province + --sans strings subject alternative names + --signature string signature algorithm for the certificate (default "SHA256") + -s, --street-address strings certificate street address +``` + +### SEE ALSO + +* [authelia crypto certificate ed25519](authelia_crypto_certificate_ed25519.md) - Perform Ed25519 certificate cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..14e28a1e --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa.md @@ -0,0 +1,43 @@ +--- +title: "authelia crypto certificate rsa" +description: "Reference for the authelia crypto certificate rsa command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate rsa + +Perform RSA certificate cryptographic operations + +### Synopsis + +Perform RSA certificate cryptographic operations. + +This subcommand allows preforming RSA certificate cryptographic tasks. + +### Examples + +``` +authelia crypto certificate rsa --help +``` + +### Options + +``` + -h, --help help for rsa +``` + +### SEE ALSO + +* [authelia crypto certificate](authelia_crypto_certificate.md) - Perform certificate cryptographic operations +* [authelia crypto certificate rsa generate](authelia_crypto_certificate_rsa_generate.md) - Generate an RSA private key and certificate +* [authelia crypto certificate rsa request](authelia_crypto_certificate_rsa_request.md) - Generate an RSA private key and certificate signing request + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..3dfc1aa3 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md @@ -0,0 +1,66 @@ +--- +title: "authelia crypto certificate rsa generate" +description: "Reference for the authelia crypto certificate rsa generate command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate rsa generate + +Generate an RSA private key and certificate + +### Synopsis + +Generate an RSA private key and certificate. + +This subcommand allows generating an RSA private key and certificate. + +``` +authelia crypto certificate rsa generate [flags] +``` + +### Examples + +``` +authelia crypto certificate rsa generate --help +``` + +### Options + +``` + -b, --bits int number of RSA bits for the certificate (default 2048) + --ca create the certificate as a certificate authority certificate + -c, --common-name string certificate common name + --country strings certificate country + -d, --directory string directory where the generated keys, certificates, etc will be stored + --duration duration duration of time the certificate is valid for (default 8760h0m0s) + --extended-usage strings specify the extended usage types of the certificate + --file.ca-certificate string certificate authority certificate to use when signing this certificate (default "ca.public.crt") + --file.ca-private-key string certificate authority private key to use to signing this certificate (default "ca.private.pem") + --file.certificate string name of the file to export the certificate data to (default "public.crt") + --file.private-key string name of the file to export the private key data to (default "private.pem") + -h, --help help for generate + -l, --locality strings certificate locality + --not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now) + -o, --organization strings certificate organization (default [Authelia]) + --organizational-unit strings certificate organizational unit + --path.ca string source directory of the certificate authority files, if not provided the certificate will be self-signed + -p, --postcode strings certificate postcode + --province strings certificate province + --sans strings subject alternative names + --signature string signature algorithm for the certificate (default "SHA256") + -s, --street-address strings certificate street address +``` + +### SEE ALSO + +* [authelia crypto certificate rsa](authelia_crypto_certificate_rsa.md) - Perform RSA certificate cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..fa2f5eec --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md @@ -0,0 +1,61 @@ +--- +title: "authelia crypto certificate rsa request" +description: "Reference for the authelia crypto certificate rsa request command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto certificate rsa request + +Generate an RSA private key and certificate signing request + +### Synopsis + +Generate an RSA private key and certificate signing request. + +This subcommand allows generating an RSA private key and certificate signing request. + +``` +authelia crypto certificate rsa request [flags] +``` + +### Examples + +``` +authelia crypto certificate rsa request --help +``` + +### Options + +``` + -b, --bits int number of RSA bits for the certificate (default 2048) + -c, --common-name string certificate common name + --country strings certificate country + -d, --directory string directory where the generated keys, certificates, etc will be stored + --duration duration duration of time the certificate is valid for (default 8760h0m0s) + --file.csr string name of the file to export the certificate request data to (default "request.csr") + --file.private-key string name of the file to export the private key data to (default "private.pem") + -h, --help help for request + -l, --locality strings certificate locality + --not-before string earliest date and time the certificate is considered valid formatted as Jan 2 15:04:05 2006 (default is now) + -o, --organization strings certificate organization (default [Authelia]) + --organizational-unit strings certificate organizational unit + -p, --postcode strings certificate postcode + --province strings certificate province + --sans strings subject alternative names + --signature string signature algorithm for the certificate (default "SHA256") + -s, --street-address strings certificate street address +``` + +### SEE ALSO + +* [authelia crypto certificate rsa](authelia_crypto_certificate_rsa.md) - Perform RSA certificate cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_pair.md b/docs/content/en/reference/cli/authelia/authelia_crypto_pair.md new file mode 100644 index 00000000..cda36b0d --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair.md @@ -0,0 +1,44 @@ +--- +title: "authelia crypto pair" +description: "Reference for the authelia crypto pair command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto pair + +Perform key pair cryptographic operations + +### Synopsis + +Perform key pair cryptographic operations. + +This subcommand allows preforming key pair cryptographic tasks. + +### Examples + +``` +authelia crypto pair --help +``` + +### Options + +``` + -h, --help help for pair +``` + +### SEE ALSO + +* [authelia crypto](authelia_crypto.md) - Perform cryptographic operations +* [authelia crypto pair ecdsa](authelia_crypto_pair_ecdsa.md) - Perform ECDSA key pair cryptographic operations +* [authelia crypto pair ed25519](authelia_crypto_pair_ed25519.md) - Perform Ed25519 key pair cryptographic operations +* [authelia crypto pair rsa](authelia_crypto_pair_rsa.md) - Perform RSA key pair cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..51fd7eea --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa.md @@ -0,0 +1,46 @@ +--- +title: "authelia crypto pair ecdsa" +description: "Reference for the authelia crypto pair ecdsa command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto pair ecdsa + +Perform ECDSA key pair cryptographic operations + +### Synopsis + +Perform ECDSA key pair cryptographic operations. + +This subcommand allows preforming ECDSA key pair cryptographic tasks. + +``` +authelia crypto pair ecdsa [flags] +``` + +### Examples + +``` +authelia crypto pair ecdsa --help +``` + +### Options + +``` + -h, --help help for ecdsa +``` + +### SEE ALSO + +* [authelia crypto pair](authelia_crypto_pair.md) - Perform key pair cryptographic operations +* [authelia crypto pair ecdsa generate](authelia_crypto_pair_ecdsa_generate.md) - Generate a cryptographic ECDSA key pair + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..84b9c4ab --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ecdsa_generate.md @@ -0,0 +1,50 @@ +--- +title: "authelia crypto pair ecdsa generate" +description: "Reference for the authelia crypto pair ecdsa generate command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto pair ecdsa generate + +Generate a cryptographic ECDSA key pair + +### Synopsis + +Generate a cryptographic ECDSA key pair. + +This subcommand allows generating an ECDSA key pair. + +``` +authelia crypto pair ecdsa generate [flags] +``` + +### Examples + +``` +authelia crypto pair ecdsa generate --help +``` + +### Options + +``` + -b, --curve string Sets the elliptic curve which can be P224, P256, P384, or P521 (default "P256") + -d, --directory string directory where the generated keys, certificates, etc will be stored + --file.private-key string name of the file to export the private key data to (default "private.pem") + --file.public-key string name of the file to export the public key data to (default "public.pem") + -h, --help help for generate + --pkcs8 force PKCS #8 ASN.1 format +``` + +### SEE ALSO + +* [authelia crypto pair ecdsa](authelia_crypto_pair_ecdsa.md) - Perform ECDSA key pair cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..e7ca06d4 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519.md @@ -0,0 +1,46 @@ +--- +title: "authelia crypto pair ed25519" +description: "Reference for the authelia crypto pair ed25519 command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto pair ed25519 + +Perform Ed25519 key pair cryptographic operations + +### Synopsis + +Perform Ed25519 key pair cryptographic operations. + +This subcommand allows preforming Ed25519 key pair cryptographic tasks. + +``` +authelia crypto pair ed25519 [flags] +``` + +### Examples + +``` +authelia crypto pair ed25519 --help +``` + +### Options + +``` + -h, --help help for ed25519 +``` + +### SEE ALSO + +* [authelia crypto pair](authelia_crypto_pair.md) - Perform key pair cryptographic operations +* [authelia crypto pair ed25519 generate](authelia_crypto_pair_ed25519_generate.md) - Generate a cryptographic Ed25519 key pair + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..6ee450a5 --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_ed25519_generate.md @@ -0,0 +1,49 @@ +--- +title: "authelia crypto pair ed25519 generate" +description: "Reference for the authelia crypto pair ed25519 generate command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto pair ed25519 generate + +Generate a cryptographic Ed25519 key pair + +### Synopsis + +Generate a cryptographic Ed25519 key pair. + +This subcommand allows generating an Ed25519 key pair. + +``` +authelia crypto pair ed25519 generate [flags] +``` + +### Examples + +``` +authelia crypto pair ed25519 generate --help +``` + +### Options + +``` + -d, --directory string directory where the generated keys, certificates, etc will be stored + --file.private-key string name of the file to export the private key data to (default "private.pem") + --file.public-key string name of the file to export the public key data to (default "public.pem") + -h, --help help for generate + --pkcs8 force PKCS #8 ASN.1 format +``` + +### SEE ALSO + +* [authelia crypto pair ed25519](authelia_crypto_pair_ed25519.md) - Perform Ed25519 key pair cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..c47386dd --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa.md @@ -0,0 +1,46 @@ +--- +title: "authelia crypto pair rsa" +description: "Reference for the authelia crypto pair rsa command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto pair rsa + +Perform RSA key pair cryptographic operations + +### Synopsis + +Perform RSA key pair cryptographic operations. + +This subcommand allows preforming RSA key pair cryptographic tasks. + +``` +authelia crypto pair rsa [flags] +``` + +### Examples + +``` +authelia crypto pair rsa --help +``` + +### Options + +``` + -h, --help help for rsa +``` + +### SEE ALSO + +* [authelia crypto pair](authelia_crypto_pair.md) - Perform key pair cryptographic operations +* [authelia crypto pair rsa generate](authelia_crypto_pair_rsa_generate.md) - Generate a cryptographic RSA key pair + +###### Auto generated by spf13/cobra on 27-Jun-2022 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 new file mode 100644 index 00000000..b806a62a --- /dev/null +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_pair_rsa_generate.md @@ -0,0 +1,50 @@ +--- +title: "authelia crypto pair rsa generate" +description: "Reference for the authelia crypto pair rsa generate command." +lead: "" +date: 2022-06-27T12:16:00+10:00 +draft: false +images: [] +menu: + reference: + parent: "cli-authelia" +weight: 330 +toc: true +--- + +## authelia crypto pair rsa generate + +Generate a cryptographic RSA key pair + +### Synopsis + +Generate a cryptographic RSA key pair. + +This subcommand allows generating an RSA key pair. + +``` +authelia crypto pair rsa generate [flags] +``` + +### Examples + +``` +authelia crypto pair rsa generate --help +``` + +### Options + +``` + -b, --bits int number of RSA bits for the certificate (default 2048) + -d, --directory string directory where the generated keys, certificates, etc will be stored + --file.private-key string name of the file to export the private key data to (default "private.pem") + --file.public-key string name of the file to export the public key data to (default "public.pem") + -h, --help help for generate + --pkcs8 force PKCS #8 ASN.1 format +``` + +### SEE ALSO + +* [authelia crypto pair rsa](authelia_crypto_pair_rsa.md) - Perform RSA key pair cryptographic operations + +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_hash-password.md b/docs/content/en/reference/cli/authelia/authelia_hash-password.md index cd66e6de..9c49414e 100644 --- a/docs/content/en/reference/cli/authelia/authelia_hash-password.md +++ b/docs/content/en/reference/cli/authelia/authelia_hash-password.md @@ -2,7 +2,7 @@ title: "authelia hash-password" description: "Reference for the authelia hash-password command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -14,7 +14,7 @@ toc: true ## authelia hash-password -Hash a password to be used in file-based users database. +Hash a password to be used in file-based users database ### Synopsis @@ -53,4 +53,4 @@ authelia hash-password --key-length=64 -- 'mypass' * [authelia](authelia.md) - authelia untagged-unknown-dirty (master, unknown) -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_rsa.md b/docs/content/en/reference/cli/authelia/authelia_rsa.md deleted file mode 100644 index ea3b6469..00000000 --- a/docs/content/en/reference/cli/authelia/authelia_rsa.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "authelia rsa" -description: "Reference for the authelia rsa command." -lead: "" -date: 2022-05-31T11:13:56+10:00 -draft: false -images: [] -menu: - reference: - parent: "cli-authelia" -weight: 330 -toc: true ---- - -## authelia rsa - -Commands related to rsa keypair generation - -### Synopsis - -Commands related to rsa keypair generation. - -This subcommand allows performing RSA keypair tasks. - -### Examples - -``` -authelia rsa --help -``` - -### Options - -``` - -h, --help help for rsa -``` - -### SEE ALSO - -* [authelia](authelia.md) - authelia untagged-unknown-dirty (master, unknown) -* [authelia rsa generate](authelia_rsa_generate.md) - Generate a RSA keypair - -###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_rsa_generate.md b/docs/content/en/reference/cli/authelia/authelia_rsa_generate.md deleted file mode 100644 index 9b80d345..00000000 --- a/docs/content/en/reference/cli/authelia/authelia_rsa_generate.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: "authelia rsa generate" -description: "Reference for the authelia rsa generate command." -lead: "" -date: 2022-05-31T11:13:56+10:00 -draft: false -images: [] -menu: - reference: - parent: "cli-authelia" -weight: 330 -toc: true ---- - -## authelia rsa generate - -Generate a RSA keypair - -### Synopsis - -Generate a RSA keypair. - -This subcommand allows generating an RSA keypair. - -``` -authelia rsa generate [flags] -``` - -### Examples - -``` -authelia rsa generate -authelia rsa generate --dir ./out -``` - -### Options - -``` - -d, --dir string Target directory where the keypair will be stored - -h, --help help for generate - -b, --key-size int Sets the key size in bits (default 2048) -``` - -### SEE ALSO - -* [authelia rsa](authelia_rsa.md) - Commands related to rsa keypair generation - -###### Auto generated by spf13/cobra on 13-Jun-2022 diff --git a/docs/content/en/reference/cli/authelia/authelia_storage.md b/docs/content/en/reference/cli/authelia/authelia_storage.md index 0423b9b6..b2fabe4c 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage.md @@ -2,7 +2,7 @@ title: "authelia storage" description: "Reference for the authelia storage command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -62,4 +62,4 @@ authelia storage --help * [authelia storage schema-info](authelia_storage_schema-info.md) - Show the storage information * [authelia storage user](authelia_storage_user.md) - Manages user settings -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 a119ec7f..8555e729 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_encryption.md @@ -2,7 +2,7 @@ title: "authelia storage encryption" description: "Reference for the authelia storage encryption command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -63,4 +63,4 @@ authelia storage encryption --help * [authelia storage encryption change-key](authelia_storage_encryption_change-key.md) - Changes the encryption key * [authelia storage encryption check](authelia_storage_encryption_check.md) - Checks the encryption key against the database data -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 f6fb2d41..0a7f6b3d 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 @@ -2,7 +2,7 @@ title: "authelia storage encryption change-key" description: "Reference for the authelia storage encryption change-key command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -67,4 +67,4 @@ authelia storage encryption change-key --encryption-key b3453fde-ecc2-4a1f-9422- * [authelia storage encryption](authelia_storage_encryption.md) - Manage storage encryption -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 96c225e8..2660c35a 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 @@ -2,7 +2,7 @@ title: "authelia storage encryption check" description: "Reference for the authelia storage encryption check command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -69,4 +69,4 @@ authelia storage encryption check --verbose --encryption-key b3453fde-ecc2-4a1f- * [authelia storage encryption](authelia_storage_encryption.md) - Manage storage encryption -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 383f2975..1819eacc 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_migrate.md @@ -2,7 +2,7 @@ title: "authelia storage migrate" description: "Reference for the authelia storage migrate command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -66,4 +66,4 @@ authelia storage migrate --help * [authelia storage migrate list-up](authelia_storage_migrate_list-up.md) - List the up migrations available * [authelia storage migrate up](authelia_storage_migrate_up.md) - Perform a migration up -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 07ee94ff..bc199733 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 @@ -2,7 +2,7 @@ title: "authelia storage migrate down" description: "Reference for the authelia storage migrate down command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -71,4 +71,4 @@ authelia storage migrate down --target 20 --encryption-key b3453fde-ecc2-4a1f-94 * [authelia storage migrate](authelia_storage_migrate.md) - Perform or list migrations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 c1b5af4e..557ecccf 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 @@ -2,7 +2,7 @@ title: "authelia storage migrate history" description: "Reference for the authelia storage migrate history command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -67,4 +67,4 @@ authelia storage migrate history --encryption-key b3453fde-ecc2-4a1f-9422-2707dd * [authelia storage migrate](authelia_storage_migrate.md) - Perform or list migrations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 b1d8f048..817d0c4f 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 @@ -2,7 +2,7 @@ title: "authelia storage migrate list-down" description: "Reference for the authelia storage migrate list-down command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -68,4 +68,4 @@ authelia storage migrate list-down --encryption-key b3453fde-ecc2-4a1f-9422-2707 * [authelia storage migrate](authelia_storage_migrate.md) - Perform or list migrations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 075ef56a..e1774f47 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 @@ -2,7 +2,7 @@ title: "authelia storage migrate list-up" description: "Reference for the authelia storage migrate list-up command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -68,4 +68,4 @@ authelia storage migrate list-up --encryption-key b3453fde-ecc2-4a1f-9422-2707dd * [authelia storage migrate](authelia_storage_migrate.md) - Perform or list migrations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 bd3d19fb..59a86b31 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 @@ -2,7 +2,7 @@ title: "authelia storage migrate up" description: "Reference for the authelia storage migrate up command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -70,4 +70,4 @@ authelia storage migrate up --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed49 * [authelia storage migrate](authelia_storage_migrate.md) - Perform or list migrations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 08a1a7cd..33d7b3b9 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 @@ -2,7 +2,7 @@ title: "authelia storage schema-info" description: "Reference for the authelia storage schema-info command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -67,4 +67,4 @@ authelia storage schema-info --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed4 * [authelia storage](authelia_storage.md) - Manage the Authelia storage -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 31ff94c2..386005e6 100644 --- a/docs/content/en/reference/cli/authelia/authelia_storage_user.md +++ b/docs/content/en/reference/cli/authelia/authelia_storage_user.md @@ -2,7 +2,7 @@ title: "authelia storage user" description: "Reference for the authelia storage user command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -63,4 +63,4 @@ authelia storage user --help * [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers * [authelia storage user totp](authelia_storage_user_totp.md) - Manage TOTP configurations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 c5c853ec..5bbf11a4 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 @@ -2,7 +2,7 @@ title: "authelia storage user identifiers" description: "Reference for the authelia storage user identifiers command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -65,4 +65,4 @@ authelia storage user identifiers --help * [authelia storage user identifiers generate](authelia_storage_user_identifiers_generate.md) - Generate opaque identifiers in bulk * [authelia storage user identifiers import](authelia_storage_user_identifiers_import.md) - Import the identifiers from a YAML file -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 7ca3f171..dcb8879d 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 @@ -2,7 +2,7 @@ title: "authelia storage user identifiers add" description: "Reference for the authelia storage user identifiers add command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -70,4 +70,4 @@ authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba- * [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 325a1c7b..64e03a02 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 @@ -2,7 +2,7 @@ title: "authelia storage user identifiers export" description: "Reference for the authelia storage user identifiers export command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -69,4 +69,4 @@ authelia storage user identifiers export --file export.yaml --encryption-key b34 * [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 5f6fd17c..fb08f0b4 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 @@ -2,7 +2,7 @@ title: "authelia storage user identifiers generate" description: "Reference for the authelia storage user identifiers generate command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -72,4 +72,4 @@ authelia storage user identifiers generate --users john,mary --services openid - * [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 cdd838cd..3fbcb27f 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 @@ -2,7 +2,7 @@ title: "authelia storage user identifiers import" description: "Reference for the authelia storage user identifiers import command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -72,4 +72,4 @@ authelia storage user identifiers import --file export.yaml --encryption-key b34 * [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 caf7c97a..af866911 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 @@ -2,7 +2,7 @@ title: "authelia storage user totp" description: "Reference for the authelia storage user totp command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -64,4 +64,4 @@ authelia storage user totp --help * [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 -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 6d0becae..3c4397c9 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 @@ -2,7 +2,7 @@ title: "authelia storage user totp delete" description: "Reference for the authelia storage user totp delete command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -67,4 +67,4 @@ authelia storage user totp delete john --encryption-key b3453fde-ecc2-4a1f-9422- * [authelia storage user totp](authelia_storage_user_totp.md) - Manage TOTP configurations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 1d186d97..49ba40fc 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 @@ -2,7 +2,7 @@ title: "authelia storage user totp export" description: "Reference for the authelia storage user totp export command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -70,4 +70,4 @@ authelia storage user totp export --format png --dir ./totp-qr --encryption-key * [authelia storage user totp](authelia_storage_user_totp.md) - Manage TOTP configurations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 23346f7c..f925807f 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 @@ -2,7 +2,7 @@ title: "authelia storage user totp generate" description: "Reference for the authelia storage user totp generate command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -79,4 +79,4 @@ authelia storage user totp generate john --algorithm SHA512 --config config.yml * [authelia storage user totp](authelia_storage_user_totp.md) - Manage TOTP configurations -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 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 a7a4a984..b90febcc 100644 --- a/docs/content/en/reference/cli/authelia/authelia_validate-config.md +++ b/docs/content/en/reference/cli/authelia/authelia_validate-config.md @@ -2,7 +2,7 @@ title: "authelia validate-config" description: "Reference for the authelia validate-config command." lead: "" -date: 2022-05-31T11:13:56+10:00 +date: 2022-06-15T17:51:47+10:00 draft: false images: [] menu: @@ -45,4 +45,4 @@ authelia validate-config --config config.yml * [authelia](authelia.md) - authelia untagged-unknown-dirty (master, unknown) -###### Auto generated by spf13/cobra on 13-Jun-2022 +###### Auto generated by spf13/cobra on 27-Jun-2022 diff --git a/examples/compose/local/setup.sh b/examples/compose/local/setup.sh index 9a0dc65d..56c211dd 100755 --- a/examples/compose/local/setup.sh +++ b/examples/compose/local/setup.sh @@ -60,7 +60,7 @@ if [[ $MODIFIED == "false" ]]; then fi echo "Generating SSL certificate for *.$DOMAIN" -sudo docker run -a stdout -v $PWD/traefik/certs:/tmp/certs authelia/authelia authelia certificates generate --host *.$DOMAIN --dir /tmp/certs/ > /dev/null +sudo docker run -a stdout -v $PWD/traefik/certs:/tmp/certs authelia/authelia authelia crypto certificate rsa generate --common-name="*.${DOMAIN}" --directory=/tmp/certs/ > /dev/null if [[ $DOMAIN != "example.com" ]]; then if [[ $(uname) == "Darwin" ]]; then diff --git a/internal/commands/certificates.go b/internal/commands/certificates.go deleted file mode 100644 index 6a0bb286..00000000 --- a/internal/commands/certificates.go +++ /dev/null @@ -1,169 +0,0 @@ -package commands - -import ( - "crypto/elliptic" - "fmt" - "log" - "os" - "path/filepath" - "time" - - "github.com/spf13/cobra" - - "github.com/authelia/authelia/v4/internal/utils" -) - -func newCertificatesCmd() (cmd *cobra.Command) { - cmd = &cobra.Command{ - Use: "certificates", - Short: cmdAutheliaCertificatesShort, - Long: cmdAutheliaCertificatesLong, - Example: cmdAutheliaCertificatesExample, - Args: cobra.NoArgs, - } - - cmd.PersistentFlags().StringSlice("host", []string{}, "Comma-separated hostnames and IPs to generate a certificate for") - - err := cmd.MarkPersistentFlagRequired("host") - if err != nil { - log.Fatal(err) - } - - cmd.AddCommand(newCertificatesGenerateCmd()) - - return cmd -} - -func newCertificatesGenerateCmd() (cmd *cobra.Command) { - cmd = &cobra.Command{ - Use: "generate", - Short: cmdAutheliaCertificatesGenerateShort, - Long: cmdAutheliaCertificatesGenerateLong, - Example: cmdAutheliaCertificatesGenerateExample, - Args: cobra.NoArgs, - Run: cmdCertificatesGenerateRun, - } - - cmd.Flags().String("start-date", "", "Creation date formatted as Jan 1 15:04:05 2011") - cmd.Flags().Duration("duration", 365*24*time.Hour, "Duration that certificate is valid for") - cmd.Flags().Bool("ca", false, "Whether this cert should be its own Certificate Authority") - cmd.Flags().Int("rsa-bits", 2048, "Size of RSA key to generate. Ignored if --ecdsa-curve is set") - cmd.Flags().String("ecdsa-curve", "", "ECDSA curve to use to generate a key. Valid values are P224, P256 (recommended), P384, P521") - cmd.Flags().Bool("ed25519", false, "Generate an Ed25519 key") - cmd.Flags().String("dir", "", "Target directory where the certificate and keys will be stored") - - return cmd -} - -func cmdCertificatesGenerateRun(cmd *cobra.Command, _ []string) { - // implementation retrieved from https://golang.org/src/crypto/tls/generate_cert.go - ecdsaCurve, err := cmd.Flags().GetString("ecdsa-curve") - if err != nil { - fmt.Printf("Failed to parse ecdsa-curve flag: %v\n", err) - os.Exit(1) - } - - ed25519Key, err := cmd.Flags().GetBool("ed25519") - if err != nil { - fmt.Printf("Failed to parse ed25519 flag: %v\n", err) - os.Exit(1) - } - - rsaBits, err := cmd.Flags().GetInt("rsa-bits") - if err != nil { - fmt.Printf("Failed to parse rsa-bits flag: %v\n", err) - os.Exit(1) - } - - hosts, err := cmd.Flags().GetStringSlice("host") - if err != nil { - fmt.Printf("Failed to parse host flag: %v\n", err) - os.Exit(1) - } - - validFrom, err := cmd.Flags().GetString("start-date") - if err != nil { - fmt.Printf("Failed to parse start-date flag: %v\n", err) - os.Exit(1) - } - - validFor, err := cmd.Flags().GetDuration("duration") - if err != nil { - fmt.Printf("Failed to parse duration flag: %v\n", err) - os.Exit(1) - } - - isCA, err := cmd.Flags().GetBool("ca") - if err != nil { - fmt.Printf("Failed to parse ca flag: %v\n", err) - os.Exit(1) - } - - certificateTargetDirectory, err := cmd.Flags().GetString("dir") - if err != nil { - fmt.Printf("Failed to parse dir flag: %v\n", err) - os.Exit(1) - } - - cmdCertificatesGenerateRunExtended(hosts, ecdsaCurve, validFrom, certificateTargetDirectory, ed25519Key, isCA, rsaBits, validFor) -} - -func cmdCertificatesGenerateRunExtended(hosts []string, ecdsaCurve, validFrom, certificateTargetDirectory string, ed25519Key, isCA bool, rsaBits int, validFor time.Duration) { - certPath := filepath.Join(certificateTargetDirectory, "cert.pem") - keyPath := filepath.Join(certificateTargetDirectory, "key.pem") - - var ( - notBefore time.Time - err error - ) - - switch len(validFrom) { - case 0: - notBefore = time.Now() - default: - notBefore, err = time.Parse("Jan 2 15:04:05 2006", validFrom) - if err != nil { - log.Fatalf("Failed to parse start date: %v", err) - } - } - - var privateKeyBuilder utils.PrivateKeyBuilder - - switch ecdsaCurve { - case "": - if ed25519Key { - privateKeyBuilder = utils.Ed25519KeyBuilder{} - } else { - privateKeyBuilder = utils.RSAKeyBuilder{}.WithKeySize(rsaBits) - } - case "P224": - privateKeyBuilder = utils.ECDSAKeyBuilder{}.WithCurve(elliptic.P224()) - case "P256": - privateKeyBuilder = utils.ECDSAKeyBuilder{}.WithCurve(elliptic.P256()) - case "P384": - privateKeyBuilder = utils.ECDSAKeyBuilder{}.WithCurve(elliptic.P384()) - case "P521": - privateKeyBuilder = utils.ECDSAKeyBuilder{}.WithCurve(elliptic.P521()) - default: - log.Fatalf("Failed to generate private key: unrecognized elliptic curve: \"%s\"", ecdsaCurve) - } - - certBytes, keyBytes, err := utils.GenerateCertificate(privateKeyBuilder, hosts, notBefore, validFor, isCA) - if err != nil { - log.Fatal(err) - } - - err = os.WriteFile(certPath, certBytes, 0600) - if err != nil { - log.Fatalf("failed to write %s for writing: %v", certPath, err) - } - - fmt.Printf("Certificate written to %s\n", certPath) - - err = os.WriteFile(keyPath, keyBytes, 0600) - if err != nil { - log.Fatalf("failed to write %s for writing: %v", certPath, err) - } - - fmt.Printf("Private Key written to %s\n", keyPath) -} diff --git a/internal/commands/const.go b/internal/commands/const.go index 008da12e..ad9cc187 100644 --- a/internal/commands/const.go +++ b/internal/commands/const.go @@ -302,41 +302,85 @@ prior to deploying it.` cmdAutheliaValidateConfigExample = `authelia validate-config authelia validate-config --config config.yml` - cmdAutheliaCertificatesShort = "Commands related to certificate generation" + cmdAutheliaCryptoShort = "Perform cryptographic operations" - cmdAutheliaCertificatesLong = `Commands related to certificate generation. + cmdAutheliaCryptoLong = `Perform cryptographic operations. -This subcommand allows preforming X509 certificate tasks.` +This subcommand allows preforming cryptographic certificate, key pair, etc tasks.` - cmdAutheliaCertificatesExample = `authelia certificates --help` + cmdAutheliaCryptoExample = `authelia crypto --help` - cmdAutheliaCertificatesGenerateShort = "Generate a self-signed certificate" + cmdAutheliaCryptoCertificateShort = "Perform certificate cryptographic operations" - cmdAutheliaCertificatesGenerateLong = `Generate a self-signed certificate. + cmdAutheliaCryptoCertificateLong = `Perform certificate cryptographic operations. -This subcommand allows generating self-signed certificates.` +This subcommand allows preforming certificate cryptographic tasks.` - cmdAutheliaCertificatesGenerateExample = `authelia certificates generate -authelia certificates generate --dir ./out` + cmdAutheliaCryptoCertificateExample = `authelia crypto certificate --help` - cmdAutheliaRSAShort = "Commands related to rsa keypair generation" + fmtCmdAutheliaCryptoCertificateSubShort = "Perform %s certificate cryptographic operations" - cmdAutheliaRSALong = `Commands related to rsa keypair generation. + fmtCmdAutheliaCryptoCertificateSubLong = `Perform %s certificate cryptographic operations. -This subcommand allows performing RSA keypair tasks.` +This subcommand allows preforming %s certificate cryptographic tasks.` - cmdAutheliaRSAExample = `authelia rsa --help` + cmdAutheliaCryptoCertificateRSAExample = `authelia crypto certificate rsa --help` - cmdAutheliaRSAGenerateShort = "Generate a RSA keypair" + cmdAutheliaCryptoCertificateECDSAExample = `authelia crypto certificate ecdsa --help` - cmdAutheliaRSAGenerateLong = `Generate a RSA keypair. + cmdAutheliaCryptoCertificateEd25519Example = `authelia crypto certificate ed25519 --help` -This subcommand allows generating an RSA keypair.` + fmtCmdAutheliaCryptoCertificateGenerateRequestShort = "Generate an %s private key and %s" - cmdAutheliaRSAGenerateExample = `authelia rsa generate -authelia rsa generate --dir ./out` + fmtCmdAutheliaCryptoCertificateGenerateRequestLong = `Generate an %s private key and %s. - cmdAutheliaHashPasswordShort = "Hash a password to be used in file-based users database." +This subcommand allows generating an %s private key and %s.` + + cmdAutheliaCryptoCertificateRSAGenerateExample = `authelia crypto certificate rsa generate --help` + + cmdAutheliaCryptoCertificateECDSAGenerateExample = `authelia crypto certificate ecdsa generate --help` + + cmdAutheliaCryptoCertificateEd25519GenerateExample = `authelia crypto certificate ed25519 request --help` + + cmdAutheliaCryptoCertificateRSARequestExample = `authelia crypto certificate rsa request --help` + + cmdAutheliaCryptoCertificateECDSARequestExample = `authelia crypto certificate ecdsa request --help` + + cmdAutheliaCryptoCertificateEd25519RequestExample = `authelia crypto certificate ed25519 request --help` + + cmdAutheliaCryptoPairShort = "Perform key pair cryptographic operations" + + cmdAutheliaCryptoPairLong = `Perform key pair cryptographic operations. + +This subcommand allows preforming key pair cryptographic tasks.` + + cmdAutheliaCryptoPairExample = `authelia crypto pair --help` + + cmdAutheliaCryptoPairSubShort = "Perform %s key pair cryptographic operations" + + cmdAutheliaCryptoPairSubLong = `Perform %s key pair cryptographic operations. + +This subcommand allows preforming %s key pair cryptographic tasks.` + + cmdAutheliaCryptoPairRSAExample = `authelia crypto pair rsa --help` + + cmdAutheliaCryptoPairECDSAExample = `authelia crypto pair ecdsa --help` + + cmdAutheliaCryptoPairEd25519Example = `authelia crypto pair ed25519 --help` + + fmtCmdAutheliaCryptoPairGenerateShort = "Generate a cryptographic %s key pair" + + fmtCmdAutheliaCryptoPairGenerateLong = `Generate a cryptographic %s key pair. + +This subcommand allows generating an %s key pair.` + + cmdAutheliaCryptoPairRSAGenerateExample = `authelia crypto pair rsa generate --help` + + cmdAutheliaCryptoPairECDSAGenerateExample = `authelia crypto pair ecdsa generate --help` + + cmdAutheliaCryptoPairEd25519GenerateExample = `authelia crypto pair ed25519 generate --help` + + cmdAutheliaHashPasswordShort = "Hash a password to be used in file-based users database" cmdAutheliaHashPasswordLong = `Hash a password to be used in file-based users database.` @@ -364,6 +408,59 @@ var ( validStorageTOTPExportFormats = []string{storageTOTPExportFormatCSV, storageTOTPExportFormatURI, storageTOTPExportFormatPNG} ) +const ( + timeLayoutCertificateNotBefore = "Jan 2 15:04:05 2006" +) + +const ( + cmdFlagNameDirectory = "directory" + + cmdFlagNamePathCA = "path.ca" + + cmdFlagNameFilePrivateKey = "file.private-key" + cmdFlagNameFilePublicKey = "file.public-key" + cmdFlagNameFileCertificate = "file.certificate" + cmdFlagNameFileCAPrivateKey = "file.ca-private-key" + cmdFlagNameFileCACertificate = "file.ca-certificate" + cmdFlagNameFileCSR = "file.csr" + + cmdFlagNameExtendedUsage = "extended-usage" + cmdFlagNameSignature = "signature" + cmdFlagNameCA = "ca" + cmdFlagNameSANs = "sans" + + cmdFlagNameCommonName = "common-name" + cmdFlagNameOrganization = "organization" + cmdFlagNameOrganizationalUnit = "organizational-unit" + cmdFlagNameCountry = "country" + cmdFlagNameProvince = "province" + cmdFlagNameLocality = "locality" + cmdFlagNameStreetAddress = "street-address" + cmdFlagNamePostcode = "postcode" + + cmdFlagNameNotBefore = "not-before" + cmdFlagNameDuration = "duration" + + cmdFlagNamePKCS8 = "pkcs8" + cmdFlagNameBits = "bits" + cmdFlagNameCurve = "curve" +) + +const ( + cmdUseCertificate = "certificate" + cmdUseGenerate = "generate" + cmdUseRequest = "request" + cmdUsePair = "pair" + cmdUseRSA = "rsa" + cmdUseECDSA = "ecdsa" + cmdUseEd25519 = "ed25519" +) + +const ( + cryptoCertPubCertOut = "certificate" + cryptoCertCSROut = "certificate signing request" +) + var ( errNoStorageProvider = errors.New("no storage provider configured") ) diff --git a/internal/commands/crypto.go b/internal/commands/crypto.go new file mode 100644 index 00000000..0035a3d2 --- /dev/null +++ b/internal/commands/crypto.go @@ -0,0 +1,451 @@ +package commands + +import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "fmt" + "strings" + "time" + + "github.com/spf13/cobra" + + "github.com/authelia/authelia/v4/internal/utils" +) + +func newCryptoCmd() (cmd *cobra.Command) { + cmd = &cobra.Command{ + Use: "crypto", + Short: cmdAutheliaCryptoShort, + Long: cmdAutheliaCryptoLong, + Example: cmdAutheliaCryptoExample, + Args: cobra.NoArgs, + } + + cmd.AddCommand( + newCryptoCertificateCmd(), + newCryptoPairCmd(), + ) + + return cmd +} + +func newCryptoCertificateCmd() (cmd *cobra.Command) { + cmd = &cobra.Command{ + Use: cmdUseCertificate, + Short: cmdAutheliaCryptoCertificateShort, + Long: cmdAutheliaCryptoCertificateLong, + Example: cmdAutheliaCryptoCertificateExample, + Args: cobra.NoArgs, + } + + cmd.AddCommand( + newCryptoCertificateSubCmd(cmdUseRSA), + newCryptoCertificateSubCmd(cmdUseECDSA), + newCryptoCertificateSubCmd(cmdUseEd25519), + ) + + return cmd +} + +func newCryptoCertificateSubCmd(use string) (cmd *cobra.Command) { + var ( + example, useFmt string + ) + + useFmt = fmtCryptoUse(use) + + switch use { + case cmdUseRSA: + example = cmdAutheliaCryptoCertificateRSAExample + case cmdUseECDSA: + example = cmdAutheliaCryptoCertificateECDSAExample + case cmdUseEd25519: + example = cmdAutheliaCryptoCertificateEd25519Example + } + + cmd = &cobra.Command{ + Use: use, + Short: fmt.Sprintf(fmtCmdAutheliaCryptoCertificateSubShort, useFmt), + Long: fmt.Sprintf(fmtCmdAutheliaCryptoCertificateSubLong, useFmt, useFmt), + Example: example, + Args: cobra.NoArgs, + } + + cmd.AddCommand(newCryptoGenerateCmd(cmdUseCertificate, use), newCryptoCertificateRequestCmd(use)) + + return cmd +} + +func newCryptoCertificateRequestCmd(algorithm string) (cmd *cobra.Command) { + cmd = &cobra.Command{ + Use: cmdUseRequest, + Args: cobra.NoArgs, + RunE: cryptoCertificateRequestRunE, + } + + cmdFlagsCryptoPrivateKey(cmd) + cmdFlagsCryptoCertificateCommon(cmd) + cmdFlagsCryptoCertificateRequest(cmd) + + algorithmFmt := fmtCryptoUse(algorithm) + + cmd.Short = fmt.Sprintf(fmtCmdAutheliaCryptoCertificateGenerateRequestShort, algorithmFmt, cryptoCertCSROut) + cmd.Long = fmt.Sprintf(fmtCmdAutheliaCryptoCertificateGenerateRequestLong, algorithmFmt, cryptoCertCSROut, algorithmFmt, cryptoCertCSROut) + + switch algorithm { + case cmdUseRSA: + cmd.Example = cmdAutheliaCryptoCertificateRSARequestExample + + cmdFlagsCryptoPrivateKeyRSA(cmd) + case cmdUseECDSA: + cmd.Example = cmdAutheliaCryptoCertificateECDSARequestExample + + cmdFlagsCryptoPrivateKeyECDSA(cmd) + case cmdUseEd25519: + cmd.Example = cmdAutheliaCryptoCertificateEd25519RequestExample + + cmdFlagsCryptoPrivateKeyEd25519(cmd) + } + + return cmd +} + +func newCryptoPairCmd() (cmd *cobra.Command) { + cmd = &cobra.Command{ + Use: cmdUsePair, + Short: cmdAutheliaCryptoPairShort, + Long: cmdAutheliaCryptoPairLong, + Example: cmdAutheliaCryptoPairExample, + Args: cobra.NoArgs, + } + + cmd.AddCommand( + newCryptoPairSubCmd(cmdUseRSA), + newCryptoPairSubCmd(cmdUseECDSA), + newCryptoPairSubCmd(cmdUseEd25519), + ) + + return cmd +} + +func newCryptoPairSubCmd(use string) (cmd *cobra.Command) { + var ( + example, useFmt string + ) + + useFmt = fmtCryptoUse(use) + + switch use { + case cmdUseRSA: + example = cmdAutheliaCryptoPairRSAExample + case cmdUseECDSA: + example = cmdAutheliaCryptoPairECDSAExample + case cmdUseEd25519: + example = cmdAutheliaCryptoPairEd25519Example + } + + cmd = &cobra.Command{ + Use: use, + Short: fmt.Sprintf(cmdAutheliaCryptoPairSubShort, useFmt), + Long: fmt.Sprintf(cmdAutheliaCryptoPairSubLong, useFmt, useFmt), + Example: example, + Args: cobra.NoArgs, + RunE: cryptoGenerateRunE, + } + + cmd.AddCommand(newCryptoGenerateCmd(cmdUsePair, use)) + + return cmd +} + +func newCryptoGenerateCmd(category, algorithm string) (cmd *cobra.Command) { + cmd = &cobra.Command{ + Use: cmdUseGenerate, + Args: cobra.NoArgs, + RunE: cryptoGenerateRunE, + } + + cmdFlagsCryptoPrivateKey(cmd) + + algorithmFmt := fmtCryptoUse(algorithm) + + switch category { + case cmdUseCertificate: + cmdFlagsCryptoCertificateCommon(cmd) + cmdFlagsCryptoCertificateGenerate(cmd) + + cmd.Short = fmt.Sprintf(fmtCmdAutheliaCryptoCertificateGenerateRequestShort, algorithmFmt, cryptoCertPubCertOut) + cmd.Long = fmt.Sprintf(fmtCmdAutheliaCryptoCertificateGenerateRequestLong, algorithmFmt, cryptoCertPubCertOut, algorithmFmt, cryptoCertPubCertOut) + + switch algorithm { + case cmdUseRSA: + cmd.Example = cmdAutheliaCryptoCertificateRSAGenerateExample + + cmdFlagsCryptoPrivateKeyRSA(cmd) + case cmdUseECDSA: + cmd.Example = cmdAutheliaCryptoCertificateECDSAGenerateExample + + cmdFlagsCryptoPrivateKeyECDSA(cmd) + case cmdUseEd25519: + cmd.Example = cmdAutheliaCryptoCertificateEd25519GenerateExample + + cmdFlagsCryptoPrivateKeyEd25519(cmd) + } + case cmdUsePair: + cmdFlagsCryptoPairGenerate(cmd) + + cmd.Short = fmt.Sprintf(fmtCmdAutheliaCryptoPairGenerateShort, algorithmFmt) + cmd.Long = fmt.Sprintf(fmtCmdAutheliaCryptoPairGenerateLong, algorithmFmt, algorithmFmt) + + switch algorithm { + case cmdUseRSA: + cmd.Example = cmdAutheliaCryptoPairRSAGenerateExample + + cmdFlagsCryptoPrivateKeyRSA(cmd) + case cmdUseECDSA: + cmd.Example = cmdAutheliaCryptoPairECDSAGenerateExample + + cmdFlagsCryptoPrivateKeyECDSA(cmd) + case cmdUseEd25519: + cmd.Example = cmdAutheliaCryptoPairEd25519GenerateExample + + cmdFlagsCryptoPrivateKeyEd25519(cmd) + } + } + + return cmd +} + +func cryptoGenerateRunE(cmd *cobra.Command, args []string) (err error) { + var ( + privateKey interface{} + ) + + if privateKey, err = cryptoGenPrivateKeyFromCmd(cmd); err != nil { + return err + } + + if cmd.Parent().Parent().Use == cmdUseCertificate { + return cryptoCertificateGenerateRunE(cmd, args, privateKey) + } + + return cryptoPairGenerateRunE(cmd, args, privateKey) +} + +func cryptoCertificateRequestRunE(cmd *cobra.Command, _ []string) (err error) { + var ( + privateKey interface{} + ) + + if privateKey, err = cryptoGenPrivateKeyFromCmd(cmd); err != nil { + return err + } + + var ( + template *x509.CertificateRequest + csr []byte + privateKeyPath, csrPath string + ) + + if template, err = cryptoGetCSRFromCmd(cmd); err != nil { + return err + } + + b := strings.Builder{} + + b.WriteString("Generating Certificate Request\n\n") + + b.WriteString("Subject:\n") + b.WriteString(fmt.Sprintf("\tCommon Name: %s, Organization: %s, Organizational Unit: %s\n", template.Subject.CommonName, template.Subject.Organization, template.Subject.OrganizationalUnit)) + b.WriteString(fmt.Sprintf("\tCountry: %v, Province: %v, Street Address: %v, Postal Code: %v, Locality: %v\n\n", template.Subject.Country, template.Subject.Province, template.Subject.StreetAddress, template.Subject.PostalCode, template.Subject.Locality)) + + b.WriteString("Properties:\n") + + b.WriteString(fmt.Sprintf("\tSignature Algorithm: %s, Public Key Algorithm: %s", template.SignatureAlgorithm, template.PublicKeyAlgorithm)) + + switch k := privateKey.(type) { + case *rsa.PrivateKey: + b.WriteString(fmt.Sprintf(", Bits: %d", k.N.BitLen())) + case *ecdsa.PrivateKey: + b.WriteString(fmt.Sprintf(", Elliptic Curve: %s", k.Curve.Params().Name)) + } + + b.WriteString(fmt.Sprintf("\n\tSubject Alternative Names: %s\n\n", strings.Join(cryptoSANsToString(template.DNSNames, template.IPAddresses), ", "))) + + if privateKeyPath, csrPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { + return err + } + + b.WriteString("Output Paths:\n") + b.WriteString(fmt.Sprintf("\tPrivate Key: %s\n", privateKeyPath)) + b.WriteString(fmt.Sprintf("\tCertificate Request: %s\n\n", csrPath)) + + fmt.Print(b.String()) + + b.Reset() + + if csr, err = x509.CreateCertificateRequest(rand.Reader, template, privateKey); err != nil { + return fmt.Errorf("failed to create certificate request: %w", err) + } + + if privateKeyPath, csrPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { + return err + } + + if err = utils.WriteKeyToPEM(privateKey, privateKeyPath, false); err != nil { + return err + } + + if err = utils.WriteCertificateBytesToPEM(csr, csrPath, true); err != nil { + return err + } + + return nil +} + +func cryptoCertificateGenerateRunE(cmd *cobra.Command, _ []string, privateKey interface{}) (err error) { + var ( + template, caCertificate, parent *x509.Certificate + publicKey, caPrivateKey, signatureKey interface{} + ) + + if publicKey = utils.PublicKeyFromPrivateKey(privateKey); publicKey == nil { + return fmt.Errorf("failed to obtain public key from private key") + } + + if caPrivateKey, caCertificate, err = cryptoGetCAFromCmd(cmd); err != nil { + return err + } + + signatureKey = privateKey + + if caPrivateKey != nil { + signatureKey = caPrivateKey + } + + if template, err = cryptoGetCertificateFromCmd(cmd); err != nil { + return err + } + + b := strings.Builder{} + + b.WriteString("Generating Certificate\n\n") + + b.WriteString(fmt.Sprintf("\tSerial: %x\n\n", template.SerialNumber)) + + switch caCertificate { + case nil: + parent = template + + b.WriteString("Signed By:\n\tSelf-Signed\n") + default: + parent = caCertificate + + b.WriteString(fmt.Sprintf("Signed By:\n\t%s\n", caCertificate.Subject.CommonName)) + b.WriteString(fmt.Sprintf("\tSerial: %x, Expires: %s\n", caCertificate.SerialNumber, caCertificate.NotAfter.Format(time.RFC3339))) + } + + b.WriteString("\nSubject:\n") + b.WriteString(fmt.Sprintf("\tCommon Name: %s, Organization: %s, Organizational Unit: %s\n", template.Subject.CommonName, template.Subject.Organization, template.Subject.OrganizationalUnit)) + b.WriteString(fmt.Sprintf("\tCountry: %v, Province: %v, Street Address: %v, Postal Code: %v, Locality: %v\n\n", template.Subject.Country, template.Subject.Province, template.Subject.StreetAddress, template.Subject.PostalCode, template.Subject.Locality)) + + b.WriteString("Properties:\n") + b.WriteString(fmt.Sprintf("\tNot Before: %s, Not After: %s\n", template.NotBefore.Format(time.RFC3339), template.NotAfter.Format(time.RFC3339))) + + b.WriteString(fmt.Sprintf("\tCA: %v, CSR: %v, Signature Algorithm: %s, Public Key Algorithm: %s", template.IsCA, false, template.SignatureAlgorithm, template.PublicKeyAlgorithm)) + + switch k := privateKey.(type) { + case *rsa.PrivateKey: + b.WriteString(fmt.Sprintf(", Bits: %d", k.N.BitLen())) + case *ecdsa.PrivateKey: + b.WriteString(fmt.Sprintf(", Elliptic Curve: %s", k.Curve.Params().Name)) + } + + b.WriteString(fmt.Sprintf("\n\tSubject Alternative Names: %s\n\n", strings.Join(cryptoSANsToString(template.DNSNames, template.IPAddresses), ", "))) + + var ( + privateKeyPath, certificatePath string + certificate []byte + ) + + if privateKeyPath, certificatePath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { + return err + } + + b.WriteString("Output Paths:\n") + b.WriteString(fmt.Sprintf("\tPrivate Key: %s\n", privateKeyPath)) + b.WriteString(fmt.Sprintf("\tCertificate: %s\n\n", certificatePath)) + + fmt.Print(b.String()) + + b.Reset() + + if certificate, err = x509.CreateCertificate(rand.Reader, template, parent, publicKey, signatureKey); err != nil { + return fmt.Errorf("failed to create certificate: %w", err) + } + + if err = utils.WriteKeyToPEM(privateKey, privateKeyPath, false); err != nil { + return err + } + + if err = utils.WriteCertificateBytesToPEM(certificate, certificatePath, false); err != nil { + return err + } + + return nil +} + +func cryptoPairGenerateRunE(cmd *cobra.Command, _ []string, privateKey interface{}) (err error) { + var ( + privateKeyPath, publicKeyPath string + pkcs8 bool + ) + + if pkcs8, err = cmd.Flags().GetBool(cmdFlagNamePKCS8); err != nil { + return err + } + + if privateKeyPath, publicKeyPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { + return err + } + + b := strings.Builder{} + + b.WriteString("Generating key pair\n\n") + + switch k := privateKey.(type) { + case *rsa.PrivateKey: + b.WriteString(fmt.Sprintf("\tAlgorithm: RSA-%d %d bits\n\n", k.Size(), k.N.BitLen())) + case *ecdsa.PrivateKey: + b.WriteString(fmt.Sprintf("\tAlgorithm: ECDSA Curve %s\n\n", k.Curve.Params().Name)) + case ed25519.PrivateKey: + b.WriteString("\tAlgorithm: Ed25519\n\n") + } + + b.WriteString("Output Paths:\n") + b.WriteString(fmt.Sprintf("\tPrivate Key: %s\n", privateKeyPath)) + b.WriteString(fmt.Sprintf("\tPublic Key: %s\n\n", publicKeyPath)) + + fmt.Print(b.String()) + + b.Reset() + + if err = utils.WriteKeyToPEM(privateKey, privateKeyPath, pkcs8); err != nil { + return err + } + + var publicKey interface{} + + if publicKey = utils.PublicKeyFromPrivateKey(privateKey); publicKey == nil { + return fmt.Errorf("failed to obtain public key from private key") + } + + if err = utils.WriteKeyToPEM(publicKey, publicKeyPath, pkcs8); err != nil { + return err + } + + return nil +} diff --git a/internal/commands/crypto_helper.go b/internal/commands/crypto_helper.go new file mode 100644 index 00000000..96e23f67 --- /dev/null +++ b/internal/commands/crypto_helper.go @@ -0,0 +1,426 @@ +package commands + +import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "fmt" + "math/big" + "net" + "os" + "path/filepath" + "strings" + "time" + + "github.com/spf13/cobra" + + "github.com/authelia/authelia/v4/internal/utils" +) + +func cmdFlagsCryptoCertificateCommon(cmd *cobra.Command) { + cmd.Flags().String(cmdFlagNameSignature, "SHA256", "signature algorithm for the certificate") + + cmd.Flags().StringP(cmdFlagNameCommonName, "c", "", "certificate common name") + cmd.Flags().StringSliceP(cmdFlagNameOrganization, "o", []string{"Authelia"}, "certificate organization") + cmd.Flags().StringSlice(cmdFlagNameOrganizationalUnit, nil, "certificate organizational unit") + cmd.Flags().StringSlice(cmdFlagNameCountry, nil, "certificate country") + cmd.Flags().StringSlice(cmdFlagNameProvince, nil, "certificate province") + cmd.Flags().StringSliceP(cmdFlagNameLocality, "l", nil, "certificate locality") + cmd.Flags().StringSliceP(cmdFlagNameStreetAddress, "s", nil, "certificate street address") + cmd.Flags().StringSliceP(cmdFlagNamePostcode, "p", nil, "certificate postcode") + + cmd.Flags().String(cmdFlagNameNotBefore, "", fmt.Sprintf("earliest date and time the certificate is considered valid formatted as %s (default is now)", timeLayoutCertificateNotBefore)) + cmd.Flags().Duration(cmdFlagNameDuration, 365*24*time.Hour, "duration of time the certificate is valid for") + cmd.Flags().StringSlice(cmdFlagNameSANs, nil, "subject alternative names") +} + +func cmdFlagsCryptoCertificateGenerate(cmd *cobra.Command) { + cmd.Flags().String(cmdFlagNamePathCA, "", "source directory of the certificate authority files, if not provided the certificate will be self-signed") + cmd.Flags().String(cmdFlagNameFileCAPrivateKey, "ca.private.pem", "certificate authority private key to use to signing this certificate") + cmd.Flags().String(cmdFlagNameFileCACertificate, "ca.public.crt", "certificate authority certificate to use when signing this certificate") + cmd.Flags().String(cmdFlagNameFileCertificate, "public.crt", "name of the file to export the certificate data to") + + cmd.Flags().StringSlice(cmdFlagNameExtendedUsage, nil, "specify the extended usage types of the certificate") + + cmd.Flags().Bool(cmdFlagNameCA, false, "create the certificate as a certificate authority certificate") +} + +func cmdFlagsCryptoCertificateRequest(cmd *cobra.Command) { + cmd.Flags().String(cmdFlagNameFileCSR, "request.csr", "name of the file to export the certificate request data to") +} + +func cmdFlagsCryptoPairGenerate(cmd *cobra.Command) { + cmd.Flags().String(cmdFlagNameFilePublicKey, "public.pem", "name of the file to export the public key data to") + cmd.Flags().Bool(cmdFlagNamePKCS8, false, "force PKCS #8 ASN.1 format") +} + +func cmdFlagsCryptoPrivateKey(cmd *cobra.Command) { + cmd.Flags().String(cmdFlagNameFilePrivateKey, "private.pem", "name of the file to export the private key data to") + cmd.Flags().StringP(cmdFlagNameDirectory, "d", "", "directory where the generated keys, certificates, etc will be stored") +} + +func cmdFlagsCryptoPrivateKeyRSA(cmd *cobra.Command) { + cmd.Flags().IntP(cmdFlagNameBits, "b", 2048, "number of RSA bits for the certificate") +} + +func cmdFlagsCryptoPrivateKeyECDSA(cmd *cobra.Command) { + cmd.Flags().StringP(cmdFlagNameCurve, "b", "P256", "Sets the elliptic curve which can be P224, P256, P384, or P521") +} + +func cmdFlagsCryptoPrivateKeyEd25519(cmd *cobra.Command) { +} + +func cryptoSANsToString(dnsSANs []string, ipSANs []net.IP) (sans []string) { + sans = make([]string, len(dnsSANs)+len(ipSANs)) + + j := 0 + + for i, dnsSAN := range dnsSANs { + sans[j] = fmt.Sprintf("DNS.%d:%s", i+1, dnsSAN) + j++ + } + + for i, ipSAN := range ipSANs { + sans[j] = fmt.Sprintf("IP.%d:%s", i+1, ipSAN) + j++ + } + + return sans +} + +func cryptoGetWritePathsFromCmd(cmd *cobra.Command) (privateKey, publicKey string, err error) { + var dir string + + if dir, err = cmd.Flags().GetString(cmdFlagNameDirectory); err != nil { + return "", "", err + } + + ca, _ := cmd.Flags().GetBool(cmdFlagNameCA) + csr := cmd.Use == cmdUseRequest + + var private, public string + + var flagPrivate, flagPublic string + + switch { + case ca && csr: + flagPrivate, flagPublic = cmdFlagNameFileCAPrivateKey, cmdFlagNameFileCSR + case csr: + flagPrivate, flagPublic = cmdFlagNameFilePrivateKey, cmdFlagNameFileCSR + case ca: + flagPrivate, flagPublic = cmdFlagNameFileCAPrivateKey, cmdFlagNameFileCACertificate + case cmd.Parent().Parent().Use == cmdUsePair: + flagPrivate, flagPublic = cmdFlagNameFilePrivateKey, cmdFlagNameFilePublicKey + default: + flagPrivate, flagPublic = cmdFlagNameFilePrivateKey, cmdFlagNameFileCertificate + } + + if private, err = cmd.Flags().GetString(flagPrivate); err != nil { + return "", "", err + } + + if public, err = cmd.Flags().GetString(flagPublic); err != nil { + return "", "", err + } + + return filepath.Join(dir, private), filepath.Join(dir, public), nil +} + +func cryptoGenPrivateKeyFromCmd(cmd *cobra.Command) (privateKey interface{}, err error) { + switch cmd.Parent().Use { + case cmdUseRSA: + var ( + bits int + ) + + if bits, err = cmd.Flags().GetInt(cmdFlagNameBits); err != nil { + return nil, err + } + + if privateKey, err = rsa.GenerateKey(rand.Reader, bits); err != nil { + return nil, fmt.Errorf("generating RSA private key resulted in an error: %w", err) + } + case cmdUseECDSA: + var ( + curveStr string + curve elliptic.Curve + ) + + if curveStr, err = cmd.Flags().GetString(cmdFlagNameCurve); err != nil { + return nil, err + } + + if curve = utils.EllipticCurveFromString(curveStr); curve == nil { + return nil, fmt.Errorf("invalid curve '%s' was specified: curve must be P224, P256, P384, or P521", curveStr) + } + + if privateKey, err = ecdsa.GenerateKey(curve, rand.Reader); err != nil { + return nil, fmt.Errorf("generating ECDSA private key resulted in an error: %w", err) + } + case cmdUseEd25519: + if _, privateKey, err = ed25519.GenerateKey(rand.Reader); err != nil { + return nil, fmt.Errorf("generating Ed25519 private key resulted in an error: %w", err) + } + } + + return privateKey, nil +} + +func cryptoGetCAFromCmd(cmd *cobra.Command) (privateKey interface{}, cert *x509.Certificate, err error) { + if !cmd.Flags().Changed(cmdFlagNamePathCA) { + return nil, nil, nil + } + + var ( + dir, filePrivateKey, fileCertificate string + + ok bool + + certificate interface{} + ) + + if dir, err = cmd.Flags().GetString(cmdFlagNamePathCA); err != nil { + return nil, nil, err + } + + if filePrivateKey, err = cmd.Flags().GetString(cmdFlagNameFileCAPrivateKey); err != nil { + return nil, nil, err + } + + if fileCertificate, err = cmd.Flags().GetString(cmdFlagNameFileCACertificate); err != nil { + return nil, nil, err + } + + var ( + bytesPrivateKey, bytesCertificate []byte + ) + + pathPrivateKey := filepath.Join(dir, filePrivateKey) + if bytesPrivateKey, err = os.ReadFile(pathPrivateKey); err != nil { + return nil, nil, fmt.Errorf("could not read private key file '%s': %w", pathPrivateKey, err) + } + + if privateKey, err = utils.ParseX509FromPEM(bytesPrivateKey); err != nil { + return nil, nil, fmt.Errorf("could not parse private key from file '%s': %w", pathPrivateKey, err) + } + + if privateKey == nil || !utils.IsX509PrivateKey(privateKey) { + return nil, nil, fmt.Errorf("could not parse private key from file '%s': does not appear to be a private key", pathPrivateKey) + } + + pathCertificate := filepath.Join(dir, fileCertificate) + if bytesCertificate, err = os.ReadFile(pathCertificate); err != nil { + return nil, nil, fmt.Errorf("could not read certificate file '%s': %w", pathCertificate, err) + } + + if certificate, err = utils.ParseX509FromPEM(bytesCertificate); err != nil { + return nil, nil, fmt.Errorf("could not parse certificate from file '%s': %w", pathCertificate, err) + } + + if cert, ok = utils.CastX509AsCertificate(certificate); !ok { + return nil, nil, fmt.Errorf("could not parse certificate from file '%s': does not appear to be a certificate", pathCertificate) + } + + return privateKey, cert, nil +} + +func cryptoGetCSRFromCmd(cmd *cobra.Command) (csr *x509.CertificateRequest, err error) { + var ( + subject *pkix.Name + dnsSANs []string + ipSANs []net.IP + ) + + if subject, err = cryptoGetSubjectFromCmd(cmd); err != nil { + return nil, err + } + + keyAlg, sigAlg := cryptoGetAlgFromCmd(cmd) + + if dnsSANs, ipSANs, err = cryptoGetSANsFromCmd(cmd); err != nil { + return nil, err + } + + csr = &x509.CertificateRequest{ + Subject: *subject, + PublicKeyAlgorithm: keyAlg, + SignatureAlgorithm: sigAlg, + + DNSNames: dnsSANs, + IPAddresses: ipSANs, + } + + return csr, nil +} + +func cryptoGetSANsFromCmd(cmd *cobra.Command) (dnsSANs []string, ipSANs []net.IP, err error) { + var ( + sans []string + ) + + if sans, err = cmd.Flags().GetStringSlice(cmdFlagNameSANs); err != nil { + return nil, nil, err + } + + for _, san := range sans { + if ipSAN := net.ParseIP(san); ipSAN != nil { + ipSANs = append(ipSANs, ipSAN) + + continue + } + + dnsSANs = append(dnsSANs, san) + } + + return dnsSANs, ipSANs, nil +} + +func cryptoGetAlgFromCmd(cmd *cobra.Command) (keyAlg x509.PublicKeyAlgorithm, sigAlg x509.SignatureAlgorithm) { + sigAlgStr, _ := cmd.Flags().GetString(cmdFlagNameSignature) + keyAlgStr := cmd.Parent().Use + + return utils.KeySigAlgorithmFromString(keyAlgStr, sigAlgStr) +} + +func cryptoGetSubjectFromCmd(cmd *cobra.Command) (subject *pkix.Name, err error) { + var ( + commonName string + organization, organizationalUnit, country, locality, province, streetAddress, postcode []string + ) + + if commonName, err = cmd.Flags().GetString(cmdFlagNameCommonName); err != nil { + return nil, err + } + + if organization, err = cmd.Flags().GetStringSlice(cmdFlagNameOrganization); err != nil { + return nil, err + } + + if organizationalUnit, err = cmd.Flags().GetStringSlice(cmdFlagNameOrganizationalUnit); err != nil { + return nil, err + } + + if country, err = cmd.Flags().GetStringSlice(cmdFlagNameCountry); err != nil { + return nil, err + } + + if locality, err = cmd.Flags().GetStringSlice(cmdFlagNameLocality); err != nil { + return nil, err + } + + if province, err = cmd.Flags().GetStringSlice(cmdFlagNameProvince); err != nil { + return nil, err + } + + if streetAddress, err = cmd.Flags().GetStringSlice(cmdFlagNameStreetAddress); err != nil { + return nil, err + } + + if postcode, err = cmd.Flags().GetStringSlice(cmdFlagNamePostcode); err != nil { + return nil, err + } + + return &pkix.Name{ + CommonName: commonName, + Organization: organization, + OrganizationalUnit: organizationalUnit, + Country: country, + Locality: locality, + Province: province, + StreetAddress: streetAddress, + PostalCode: postcode, + }, nil +} + +func cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate *x509.Certificate, err error) { + var ( + ca bool + subject *pkix.Name + notBeforeStr string + duration time.Duration + ) + + if ca, err = cmd.Flags().GetBool(cmdFlagNameCA); err != nil { + return nil, err + } + + if subject, err = cryptoGetSubjectFromCmd(cmd); err != nil { + return nil, err + } + + if notBeforeStr, err = cmd.Flags().GetString(cmdFlagNameNotBefore); err != nil { + return nil, err + } + + if duration, err = cmd.Flags().GetDuration(cmdFlagNameDuration); err != nil { + return nil, err + } + + var ( + notBefore time.Time + serialNumber *big.Int + dnsSANs, extKeyUsages []string + ipSANs []net.IP + ) + + switch len(notBeforeStr) { + case 0: + notBefore = time.Now() + default: + if notBefore, err = time.Parse(timeLayoutCertificateNotBefore, notBeforeStr); err != nil { + return nil, fmt.Errorf("failed to parse not before: %w", err) + } + } + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + + if serialNumber, err = rand.Int(rand.Reader, serialNumberLimit); err != nil { + return nil, fmt.Errorf("failed to generate serial number: %w", err) + } + + if dnsSANs, ipSANs, err = cryptoGetSANsFromCmd(cmd); err != nil { + return nil, err + } + + keyAlg, sigAlg := cryptoGetAlgFromCmd(cmd) + + if extKeyUsages, err = cmd.Flags().GetStringSlice(cmdFlagNameExtendedUsage); err != nil { + return nil, err + } + + certificate = &x509.Certificate{ + SerialNumber: serialNumber, + Subject: *subject, + + NotBefore: notBefore, + NotAfter: notBefore.Add(duration), + + IsCA: ca, + + KeyUsage: utils.X509ParseKeyUsage(nil, ca), + ExtKeyUsage: utils.X509ParseExtendedKeyUsage(extKeyUsages, ca), + + PublicKeyAlgorithm: keyAlg, + SignatureAlgorithm: sigAlg, + + DNSNames: dnsSANs, + IPAddresses: ipSANs, + + BasicConstraintsValid: true, + } + + return certificate, nil +} + +func fmtCryptoUse(use string) string { + switch use { + case cmdUseEd25519: + return "Ed25519" + default: + return strings.ToUpper(use) + } +} diff --git a/internal/commands/root.go b/internal/commands/root.go index 52face48..071c0342 100644 --- a/internal/commands/root.go +++ b/internal/commands/root.go @@ -36,9 +36,8 @@ func NewRootCmd() (cmd *cobra.Command) { cmd.AddCommand( newBuildInfoCmd(), - newCertificatesCmd(), + newCryptoCmd(), newHashPasswordCmd(), - NewRSACmd(), newStorageCmd(), newValidateConfigCmd(), newAccessControlCommand(), diff --git a/internal/commands/rsa.go b/internal/commands/rsa.go deleted file mode 100644 index 4b898332..00000000 --- a/internal/commands/rsa.go +++ /dev/null @@ -1,110 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "path/filepath" - - "github.com/spf13/cobra" - - "github.com/authelia/authelia/v4/internal/utils" -) - -// NewRSACmd returns a new RSA Cmd. -func NewRSACmd() (cmd *cobra.Command) { - cmd = &cobra.Command{ - Use: "rsa", - Short: cmdAutheliaRSAShort, - Long: cmdAutheliaRSALong, - Example: cmdAutheliaRSAExample, - Args: cobra.NoArgs, - } - - cmd.AddCommand(newRSAGenerateCmd()) - - return cmd -} - -func newRSAGenerateCmd() (cmd *cobra.Command) { - cmd = &cobra.Command{ - Use: "generate", - Short: cmdAutheliaRSAGenerateShort, - Long: cmdAutheliaRSAGenerateLong, - Example: cmdAutheliaRSAGenerateExample, - Args: cobra.NoArgs, - Run: cmdRSAGenerateRun, - } - - cmd.Flags().StringP("dir", "d", "", "Target directory where the keypair will be stored") - cmd.Flags().IntP("key-size", "b", 2048, "Sets the key size in bits") - - return cmd -} - -func cmdRSAGenerateRun(cmd *cobra.Command, _ []string) { - bits, err := cmd.Flags().GetInt("key-size") - if err != nil { - fmt.Printf("Failed to parse key-size flag: %v\n", err) - return - } - - privateKey, publicKey := utils.GenerateRsaKeyPair(bits) - - rsaTargetDirectory, err := cmd.Flags().GetString("dir") - if err != nil { - fmt.Printf("Failed to parse dir flag: %v\n", err) - return - } - - keyPath := filepath.Join(rsaTargetDirectory, "key.pem") - - keyOut, err := os.OpenFile(keyPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - fmt.Printf("Failed to open %s for writing: %v\n", keyPath, err) - return - } - - defer func() { - if err := keyOut.Close(); err != nil { - fmt.Printf("Unable to close private key file: %v\n", err) - os.Exit(1) - } - }() - - _, err = keyOut.WriteString(utils.ExportRsaPrivateKeyAsPemStr(privateKey)) - if err != nil { - fmt.Printf("Failed to write private key: %v\n", err) - return - } - - fmt.Printf("RSA Private Key written to %s\n", keyPath) - - certPath := filepath.Join(rsaTargetDirectory, "key.pub") - - certOut, err := os.OpenFile(certPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - fmt.Printf("Failed to open %s for writing: %v\n", keyPath, err) - return - } - - defer func() { - if err := certOut.Close(); err != nil { - fmt.Printf("Failed to close public key file: %v\n", err) - os.Exit(1) - } - }() - - publicPem, err := utils.ExportRsaPublicKeyAsPemStr(publicKey) - if err != nil { - fmt.Printf("Failed to marshal public key: %v\n", err) - return - } - - _, err = certOut.WriteString(publicPem) - if err != nil { - fmt.Printf("Failed to write private key: %v\n", err) - return - } - - fmt.Printf("RSA Public Key written to %s\n", certPath) -} diff --git a/internal/oidc/keys.go b/internal/oidc/keys.go index 8460efbf..94652625 100644 --- a/internal/oidc/keys.go +++ b/internal/oidc/keys.go @@ -86,11 +86,17 @@ func (m KeyManager) GetActivePrivateKey() (key *rsa.PrivateKey, err error) { // AddActivePrivateKeyData adds a rsa.PublicKey given the key in the PEM string format, then sets it to the active key. func (m *KeyManager) AddActivePrivateKeyData(data string) (key *rsa.PrivateKey, webKey *jose.JSONWebKey, err error) { - key, err = utils.ParseRsaPrivateKeyFromPemStr(data) + ikey, err := utils.ParseX509FromPEM([]byte(data)) if err != nil { return nil, nil, err } + var ok bool + + if key, ok = ikey.(*rsa.PrivateKey); !ok { + return nil, nil, errors.New("key must be an RSA private key") + } + webKey, err = m.AddActivePrivateKey(key) return key, webKey, err diff --git a/internal/suites/suite_cli_test.go b/internal/suites/suite_cli_test.go index 74edcf01..b236e1dd 100644 --- a/internal/suites/suite_cli_test.go +++ b/internal/suites/suite_cli_test.go @@ -1,6 +1,7 @@ package suites import ( + "bytes" "context" "fmt" "os" @@ -13,6 +14,7 @@ import ( "github.com/authelia/authelia/v4/internal/model" "github.com/authelia/authelia/v4/internal/storage" + "github.com/authelia/authelia/v4/internal/utils" ) type CLISuite struct { @@ -37,7 +39,7 @@ func (s *CLISuite) SetupTest() { coverageArg := "" if os.Getenv("CI") == t { - testArg = "-test.coverprofile=/authelia/coverage-$(date +%s).txt" + testArg = "-test.coverprofile=/authelia/coverage-$(cat /proc/sys/kernel/random/uuid).txt" coverageArg = "COVERAGE" } @@ -94,79 +96,526 @@ func (s *CLISuite) TestShouldHashPasswordSHA512() { s.Assert().Contains(output, "Password hash: $6$rounds=50000") } -func (s *CLISuite) TestShouldGenerateCertificateRSA() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/"}) +func (s *CLISuite) TestShouldGenerateRSACertificateRequest() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "request", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") + s.Assert().Contains(output, "Generating Certificate Request") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tSignature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate Request: /tmp/request.csr") +} + +func (s *CLISuite) TestShouldGenerateECDSACurveP224CertificateRequest() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "request", "--curve=P224", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate Request") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tSignature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-224") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate Request: /tmp/request.csr") +} + +func (s *CLISuite) TestShouldGenerateECDSACurveP256CertificateRequest() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "request", "--curve=P256", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate Request") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tSignature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-256") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate Request: /tmp/request.csr") +} + +func (s *CLISuite) TestShouldGenerateECDSACurveP384CertificateRequest() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "request", "--curve=P384", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate Request") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tSignature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-384") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate Request: /tmp/request.csr") +} + +func (s *CLISuite) TestShouldGenerateECDSACurveP521CertificateRequest() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "request", "--curve=P521", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate Request") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tSignature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-521") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate Request: /tmp/request.csr") +} + +func (s *CLISuite) TestShouldGenerateEd25519CertificateRequest() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ed25519", "request", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate Request") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tSignature Algorithm: Ed25519, Public Key Algorithm: Ed25519") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate Request: /tmp/request.csr") +} + +func (s *CLISuite) TestShouldGenerateCertificateRSA() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") } func (s *CLISuite) TestShouldGenerateCertificateRSAWithIPAddress() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=127.0.0.1", "--dir=/tmp/"}) + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans", "*.example.com,127.0.0.1", "--directory=/tmp/"}) s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com, IP.1:127.0.0.1") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") } -func (s *CLISuite) TestShouldGenerateCertificateRSAWithStartDate() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--start-date='Jan 1 15:04:05 2011'"}) +func (s *CLISuite) TestShouldGenerateCertificateRSAWithNotBefore() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--not-before", "'Jan 1 15:04:05 2011'", "--directory=/tmp/"}) s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tNot Before: 2011-01-01T15:04:05Z, Not After: 2012-01-01T15:04:05Z") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") } -func (s *CLISuite) TestShouldFailGenerateCertificateRSAWithStartDate() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--start-date=Jan"}) +func (s *CLISuite) TestShouldFailGenerateCertificateRSAWithInvalidNotBefore() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--not-before", "Jan", "--directory=/tmp/"}) s.Assert().NotNil(err) - s.Assert().Contains(output, "Failed to parse start date: parsing time \"Jan\" as \"Jan 2 15:04:05 2006\": cannot parse \"\" as \"2\"") + s.Assert().Contains(output, "Error: failed to parse not before: parsing time \"Jan\" as \"Jan 2 15:04:05 2006\": cannot parse \"\" as \"2\"") +} + +func (s *CLISuite) TestShouldGenerateCertificateRSAWith4096Bits() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--bits=4096", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 4096") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") +} + +func (s *CLISuite) TestShouldGenerateCertificateWithCustomizedSubject() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--country=Australia", "--organization='Acme Co.'", "--organizational-unit=Tech", "--province=QLD", "--street-address='123 Smith St'", "--postcode=4000", "--locality=Internet", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Acme Co.], Organizational Unit: [Tech]") + s.Assert().Contains(output, "\tCountry: [Australia], Province: [QLD], Street Address: [123 Smith St], Postal Code: [4000], Locality: [Internet]") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") } func (s *CLISuite) TestShouldGenerateCertificateCA() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ca"}) + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: Authelia Standalone Root Certificate Authority, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: true, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048") + s.Assert().Contains(output, "\tSubject Alternative Names: ") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/ca.private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/ca.public.crt") +} + +func (s *CLISuite) TestShouldGenerateCertificateCAAndSignCertificate() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: Authelia Standalone Root Certificate Authority, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: true, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048") + s.Assert().Contains(output, "\tSubject Alternative Names: ") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/ca.private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/ca.public.crt") + + output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--path.ca", "/tmp/", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tAuthelia Standalone Root Certificate Authority") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, ", Expires: ") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: SHA256-RSA, Public Key Algorithm: RSA, Bits: 2048") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") + + // Check the certificates look fine. + privateKeyData, err := os.ReadFile("/tmp/private.pem") + s.Assert().NoError(err) + + certificateData, err := os.ReadFile("/tmp/public.crt") + s.Assert().NoError(err) + + privateKeyCAData, err := os.ReadFile("/tmp/ca.private.pem") + s.Assert().NoError(err) + + certificateCAData, err := os.ReadFile("/tmp/ca.public.crt") + s.Assert().NoError(err) + + s.Assert().False(bytes.Equal(privateKeyData, privateKeyCAData)) + s.Assert().False(bytes.Equal(certificateData, certificateCAData)) + + privateKey, err := utils.ParseX509FromPEM(privateKeyData) + s.Assert().NoError(err) + s.Assert().True(utils.IsX509PrivateKey(privateKey)) + + privateCAKey, err := utils.ParseX509FromPEM(privateKeyCAData) + s.Assert().NoError(err) + s.Assert().True(utils.IsX509PrivateKey(privateCAKey)) + + c, err := utils.ParseX509FromPEM(certificateData) + s.Assert().NoError(err) + s.Assert().False(utils.IsX509PrivateKey(c)) + + cCA, err := utils.ParseX509FromPEM(certificateCAData) + s.Assert().NoError(err) + s.Assert().False(utils.IsX509PrivateKey(cCA)) + + certificate, ok := utils.CastX509AsCertificate(c) + s.Assert().True(ok) + + certificateCA, ok := utils.CastX509AsCertificate(cCA) + s.Assert().True(ok) + + s.Require().NotNil(certificate) + s.Require().NotNil(certificateCA) + + err = certificate.CheckSignatureFrom(certificateCA) + s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") } func (s *CLISuite) TestShouldGenerateCertificateEd25519() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ed25519"}) + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ed25519", "generate", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: Ed25519, Public Key Algorithm: Ed25519") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") +} + +func (s *CLISuite) TestShouldFailGenerateCertificateParseNotBefore() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--not-before=invalid", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) + s.Assert().NotNil(err) + s.Assert().Contains(output, "Error: failed to parse not before: parsing time \"invalid\" as \"Jan 2 15:04:05 2006\": cannot parse \"invalid\" as \"Jan\"") } func (s *CLISuite) TestShouldFailGenerateCertificateECDSA() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=invalid"}) + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=invalid", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) s.Assert().NotNil(err) - s.Assert().Contains(output, "Failed to generate private key: unrecognized elliptic curve: \"invalid\"") + s.Assert().Contains(output, "Error: invalid curve 'invalid' was specified: curve must be P224, P256, P384, or P521") } -func (s *CLISuite) TestShouldGenerateCertificateECDSAP224() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=P224"}) +func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP224() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=P224", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-224") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") } -func (s *CLISuite) TestShouldGenerateCertificateECDSAP256() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=P256"}) +func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP256() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=P256", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-256") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") } -func (s *CLISuite) TestShouldGenerateCertificateECDSAP384() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=P384"}) +func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP384() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=P384", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-384") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") } -func (s *CLISuite) TestShouldGenerateCertificateECDSAP521() { - output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "certificates", "generate", "--host=*.example.com", "--dir=/tmp/", "--ecdsa-curve=P521"}) +func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP521() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=P521", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"}) s.Assert().NoError(err) - s.Assert().Contains(output, "Certificate written to /tmp/cert.pem") - s.Assert().Contains(output, "Private Key written to /tmp/key.pem") + s.Assert().Contains(output, "Generating Certificate") + s.Assert().Contains(output, "\tSerial: ") + s.Assert().Contains(output, "Signed By:\n\tSelf-Signed") + + s.Assert().Contains(output, "\tCommon Name: example.com, Organization: [Authelia], Organizational Unit: []") + s.Assert().Contains(output, "\tCountry: [], Province: [], Street Address: [], Postal Code: [], Locality: []") + s.Assert().Contains(output, "\tCA: false, CSR: false, Signature Algorithm: ECDSA-SHA256, Public Key Algorithm: ECDSA, Elliptic Curve: P-521") + s.Assert().Contains(output, "\tSubject Alternative Names: DNS.1:*.example.com") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tCertificate: /tmp/public.crt") +} + +func (s *CLISuite) TestShouldGenerateRSAKeyPair() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "rsa", "generate", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating key pair") + + s.Assert().Contains(output, "Algorithm: RSA-256 2048 bits\n\n") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tPublic Key: /tmp/public.pem") +} + +func (s *CLISuite) TestShouldGenerateRSAKeyPairWith4069Bits() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "rsa", "generate", "--bits=4096", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating key pair") + + s.Assert().Contains(output, "Algorithm: RSA-512 4096 bits\n\n") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tPublic Key: /tmp/public.pem") +} + +func (s *CLISuite) TestShouldGenerateECDSAKeyPair() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating key pair") + + s.Assert().Contains(output, "Algorithm: ECDSA Curve P-256\n\n") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tPublic Key: /tmp/public.pem") +} + +func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP224() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=P224", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating key pair") + + s.Assert().Contains(output, "Algorithm: ECDSA Curve P-224\n\n") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tPublic Key: /tmp/public.pem") +} + +func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP256() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=P256", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating key pair") + + s.Assert().Contains(output, "Algorithm: ECDSA Curve P-256\n\n") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tPublic Key: /tmp/public.pem") +} + +func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP384() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=P384", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating key pair") + + s.Assert().Contains(output, "Algorithm: ECDSA Curve P-384\n\n") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tPublic Key: /tmp/public.pem") +} + +func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP521() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=P521", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating key pair") + + s.Assert().Contains(output, "Algorithm: ECDSA Curve P-521\n\n") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tPublic Key: /tmp/public.pem") +} + +func (s *CLISuite) TestShouldGenerateEd25519KeyPair() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ed25519", "generate", "--directory=/tmp/"}) + s.Assert().NoError(err) + s.Assert().Contains(output, "Generating key pair") + + s.Assert().Contains(output, "Algorithm: Ed25519\n\n") + + s.Assert().Contains(output, "Output Paths:") + s.Assert().Contains(output, "\tPrivate Key: /tmp/private.pem") + s.Assert().Contains(output, "\tPublic Key: /tmp/public.pem") +} + +func (s *CLISuite) TestShouldNotGenerateECDSAKeyPairCurveInvalid() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=invalid", "--directory=/tmp/"}) + s.Assert().NotNil(err) + s.Assert().Contains(output, "Error: invalid curve 'invalid' was specified: curve must be P224, P256, P384, or P521") +} + +func (s *CLISuite) TestShouldNotGenerateRSAWithBadCAPath() { + output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/invalid", "--directory=/tmp/"}) + s.Assert().NotNil(err) + s.Assert().Contains(output, "Error: could not read private key file '/tmp/invalid/ca.private.pem': open /tmp/invalid/ca.private.pem: no such file or directory\n") +} + +func (s *CLISuite) TestShouldNotGenerateRSAWithBadCAFileNames() { + var ( + err error + output string + ) + + _, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"}) + s.Assert().NoError(err) + + output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-private-key=invalid.pem", "--directory=/tmp/"}) + s.Assert().NotNil(err) + s.Assert().Contains(output, "Error: could not read private key file '/tmp/invalid.pem': open /tmp/invalid.pem: no such file or directory\n") + + output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-certificate=invalid.crt", "--directory=/tmp/"}) + s.Assert().NotNil(err) + s.Assert().Contains(output, "Error: could not read certificate file '/tmp/invalid.crt': open /tmp/invalid.crt: no such file or directory\n") +} + +func (s *CLISuite) TestShouldNotGenerateRSAWithBadCAFileContent() { + var ( + err error + output string + ) + + _, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"}) + s.Assert().NoError(err) + + s.Require().NoError(os.WriteFile("/tmp/ca.private.bad.pem", []byte("INVALID"), 0600)) //nolint:gosec + s.Require().NoError(os.WriteFile("/tmp/ca.public.bad.crt", []byte("INVALID"), 0600)) //nolint:gosec + + output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-private-key=ca.private.bad.pem", "--directory=/tmp/"}) + s.Assert().NotNil(err) + s.Assert().Contains(output, "Error: could not parse private key from file '/tmp/ca.private.bad.pem': failed to parse PEM block containing the key\n") + + output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-certificate=ca.public.bad.crt", "--directory=/tmp/"}) + s.Assert().NotNil(err) + s.Assert().Contains(output, "Error: could not parse certificate from file '/tmp/ca.public.bad.crt': failed to parse PEM block containing the key\n") } func (s *CLISuite) TestStorageShouldShowErrWithoutConfig() { diff --git a/internal/suites/utils.go b/internal/suites/utils.go index 810806ec..e2efc562 100644 --- a/internal/suites/utils.go +++ b/internal/suites/utils.go @@ -8,9 +8,9 @@ import ( "path/filepath" "runtime" "strings" - "time" "github.com/go-rod/rod" + "github.com/google/uuid" ) // GetLoginBaseURL returns the URL of the login portal and the path prefix if specified. @@ -24,7 +24,6 @@ func GetLoginBaseURL() string { func (rs *RodSession) collectCoverage(page *rod.Page) { coverageDir := "../../web/.nyc_output" - now := time.Now() resp, err := page.Eval("() => JSON.stringify(window.__coverage__)") if err != nil { @@ -36,7 +35,7 @@ func (rs *RodSession) collectCoverage(page *rod.Page) { _ = os.MkdirAll(coverageDir, 0775) if coverageData != "" { - err = os.WriteFile(fmt.Sprintf("%s/coverage-%d.json", coverageDir, now.Unix()), []byte(coverageData), 0664) //nolint:gosec + err = os.WriteFile(fmt.Sprintf("%s/coverage-%s.json", coverageDir, uuid.New().String()), []byte(coverageData), 0664) //nolint:gosec if err != nil { log.Fatal(err) } diff --git a/internal/utils/certificates.go b/internal/utils/certificates.go deleted file mode 100644 index bc7d2952..00000000 --- a/internal/utils/certificates.go +++ /dev/null @@ -1,253 +0,0 @@ -package utils - -import ( - "bytes" - "crypto/ecdsa" - "crypto/ed25519" - "crypto/elliptic" - "crypto/rand" - "crypto/rsa" - "crypto/tls" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "fmt" - "math/big" - "net" - "os" - "path/filepath" - "strings" - "time" - - "github.com/authelia/authelia/v4/internal/configuration/schema" - "github.com/authelia/authelia/v4/internal/logging" -) - -// PEMBlockType represent an enum of the existing PEM block types. -type PEMBlockType int - -const ( - // Certificate block type. - Certificate PEMBlockType = iota - // PrivateKey block type. - PrivateKey -) - -// NewTLSConfig generates a tls.Config from a schema.TLSConfig and a x509.CertPool. -func NewTLSConfig(config *schema.TLSConfig, defaultMinVersion uint16, certPool *x509.CertPool) (tlsConfig *tls.Config) { - minVersion, err := TLSStringToTLSConfigVersion(config.MinimumVersion) - if err != nil { - minVersion = defaultMinVersion - } - - return &tls.Config{ - ServerName: config.ServerName, - InsecureSkipVerify: config.SkipVerify, //nolint:gosec // Informed choice by user. Off by default. - MinVersion: minVersion, - RootCAs: certPool, - } -} - -// NewX509CertPool generates a x509.CertPool from the system PKI and the directory specified. -func NewX509CertPool(directory string) (certPool *x509.CertPool, warnings []error, errors []error) { - certPool, err := x509.SystemCertPool() - if err != nil { - warnings = append(warnings, fmt.Errorf("could not load system certificate pool which may result in untrusted certificate issues: %v", err)) - certPool = x509.NewCertPool() - } - - logger := logging.Logger() - - logger.Tracef("Starting scan of directory %s for certificates", directory) - - if directory != "" { - certsFileInfo, err := os.ReadDir(directory) - if err != nil { - errors = append(errors, fmt.Errorf("could not read certificates from directory %v", err)) - } else { - for _, certFileInfo := range certsFileInfo { - nameLower := strings.ToLower(certFileInfo.Name()) - - if !certFileInfo.IsDir() && (strings.HasSuffix(nameLower, ".cer") || strings.HasSuffix(nameLower, ".crt") || strings.HasSuffix(nameLower, ".pem")) { - certPath := filepath.Join(directory, certFileInfo.Name()) - - logger.Tracef("Found possible cert %s, attempting to add it to the pool", certPath) - - certBytes, err := os.ReadFile(certPath) - if err != nil { - errors = append(errors, fmt.Errorf("could not read certificate %v", err)) - } else if ok := certPool.AppendCertsFromPEM(certBytes); !ok { - errors = append(errors, fmt.Errorf("could not import certificate %s", certFileInfo.Name())) - } - } - } - } - } - - logger.Tracef("Finished scan of directory %s for certificates", directory) - - return certPool, warnings, errors -} - -// TLSStringToTLSConfigVersion returns a go crypto/tls version for a tls.Config based on string input. -func TLSStringToTLSConfigVersion(input string) (version uint16, err error) { - switch strings.ToUpper(input) { - case "TLS1.3", TLS13: - return tls.VersionTLS13, nil - case "TLS1.2", TLS12: - return tls.VersionTLS12, nil - case "TLS1.1", TLS11: - return tls.VersionTLS11, nil - case "TLS1.0", TLS10: - return tls.VersionTLS10, nil - } - - return 0, ErrTLSVersionNotSupported -} - -// GenerateCertificate generate a certificate given a private key. RSA, Ed25519 and ECDSA are officially supported. -func GenerateCertificate(privateKeyBuilder PrivateKeyBuilder, hosts []string, validFrom time.Time, validFor time.Duration, isCA bool) ([]byte, []byte, error) { - privateKey, err := privateKeyBuilder.Build() - if err != nil { - return nil, nil, fmt.Errorf("unable to build private key: %w", err) - } - - notBefore := validFrom - notAfter := validFrom.Add(validFor) - - serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) - - serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) - if err != nil { - return nil, nil, fmt.Errorf("failed to generate serial number: %v", err) - } - - template := x509.Certificate{ - SerialNumber: serialNumber, - Subject: pkix.Name{ - Organization: []string{"Acme Co"}, - }, - NotBefore: notBefore, - NotAfter: notAfter, - - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, - BasicConstraintsValid: true, - } - - for _, h := range hosts { - if ip := net.ParseIP(h); ip != nil { - template.IPAddresses = append(template.IPAddresses, ip) - } else { - template.DNSNames = append(template.DNSNames, h) - } - } - - if isCA { - template.IsCA = true - template.KeyUsage |= x509.KeyUsageCertSign - } - - certDERBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(privateKey), privateKey) - if err != nil { - return nil, nil, fmt.Errorf("failed to create certificate: %v", err) - } - - certPEMBytes, err := ConvertDERToPEM(certDERBytes, Certificate) - if err != nil { - return nil, nil, fmt.Errorf("faile to convert certificate in DER format into PEM: %v", err) - } - - keyDERBytes, err := x509.MarshalPKCS8PrivateKey(privateKey) - if err != nil { - return nil, nil, fmt.Errorf("failed to marshal private key: %v", err) - } - - keyPEMBytes, err := ConvertDERToPEM(keyDERBytes, PrivateKey) - if err != nil { - return nil, nil, fmt.Errorf("faile to convert certificate in DER format into PEM: %v", err) - } - - return certPEMBytes, keyPEMBytes, nil -} - -// ConvertDERToPEM convert certificate in DER format into PEM format. -func ConvertDERToPEM(der []byte, blockType PEMBlockType) ([]byte, error) { - var buf bytes.Buffer - - var blockTypeStr string - - switch blockType { - case Certificate: - blockTypeStr = "CERTIFICATE" - case PrivateKey: - blockTypeStr = "PRIVATE KEY" - default: - return nil, fmt.Errorf("unknown PEM block type %d", blockType) - } - - if err := pem.Encode(&buf, &pem.Block{Type: blockTypeStr, Bytes: der}); err != nil { - return nil, fmt.Errorf("failed to encode DER data into PEM: %v", err) - } - - return buf.Bytes(), nil -} - -func publicKey(privateKey interface{}) interface{} { - switch k := privateKey.(type) { - case *rsa.PrivateKey: - return &k.PublicKey - case *ecdsa.PrivateKey: - return &k.PublicKey - case ed25519.PrivateKey: - return k.Public().(ed25519.PublicKey) - default: - return nil - } -} - -// PrivateKeyBuilder interface for a private key builder. -type PrivateKeyBuilder interface { - Build() (interface{}, error) -} - -// RSAKeyBuilder builder of RSA private key. -type RSAKeyBuilder struct { - keySizeInBits int -} - -// WithKeySize configure the key size to use with RSA. -func (rkb RSAKeyBuilder) WithKeySize(bits int) RSAKeyBuilder { - rkb.keySizeInBits = bits - return rkb -} - -// Build a RSA private key. -func (rkb RSAKeyBuilder) Build() (interface{}, error) { - return rsa.GenerateKey(rand.Reader, rkb.keySizeInBits) -} - -// Ed25519KeyBuilder builder of Ed25519 private key. -type Ed25519KeyBuilder struct{} - -// Build an Ed25519 private key. -func (ekb Ed25519KeyBuilder) Build() (interface{}, error) { - _, priv, err := ed25519.GenerateKey(rand.Reader) - return priv, err -} - -// ECDSAKeyBuilder builder of ECDSA private key. -type ECDSAKeyBuilder struct { - curve elliptic.Curve -} - -// WithCurve configure the curve to use for the ECDSA private key. -func (ekb ECDSAKeyBuilder) WithCurve(curve elliptic.Curve) ECDSAKeyBuilder { - ekb.curve = curve - return ekb -} - -// Build an ECDSA private key. -func (ekb ECDSAKeyBuilder) Build() (interface{}, error) { - return ecdsa.GenerateKey(ekb.curve, rand.Reader) -} diff --git a/internal/utils/certificates_test.go b/internal/utils/certificates_test.go deleted file mode 100644 index 918678fe..00000000 --- a/internal/utils/certificates_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package utils - -import ( - "crypto/elliptic" - "crypto/tls" - "runtime" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/authelia/authelia/v4/internal/configuration/schema" -) - -func TestShouldSetupDefaultTLSMinVersionOnErr(t *testing.T) { - schemaTLSConfig := &schema.TLSConfig{ - MinimumVersion: "NotAVersion", - ServerName: "golang.org", - SkipVerify: true, - } - - tlsConfig := NewTLSConfig(schemaTLSConfig, tls.VersionTLS12, nil) - - assert.Equal(t, uint16(tls.VersionTLS12), tlsConfig.MinVersion) - assert.Equal(t, "golang.org", tlsConfig.ServerName) - assert.True(t, tlsConfig.InsecureSkipVerify) -} - -func TestShouldReturnCorrectTLSVersions(t *testing.T) { - tls13 := uint16(tls.VersionTLS13) - tls12 := uint16(tls.VersionTLS12) - tls11 := uint16(tls.VersionTLS11) - tls10 := uint16(tls.VersionTLS10) - - version, err := TLSStringToTLSConfigVersion(TLS13) - assert.Equal(t, tls13, version) - assert.NoError(t, err) - - version, err = TLSStringToTLSConfigVersion("TLS" + TLS13) - assert.Equal(t, tls13, version) - assert.NoError(t, err) - - version, err = TLSStringToTLSConfigVersion(TLS12) - assert.Equal(t, tls12, version) - assert.NoError(t, err) - - version, err = TLSStringToTLSConfigVersion("TLS" + TLS12) - assert.Equal(t, tls12, version) - assert.NoError(t, err) - - version, err = TLSStringToTLSConfigVersion(TLS11) - assert.Equal(t, tls11, version) - assert.NoError(t, err) - - version, err = TLSStringToTLSConfigVersion("TLS" + TLS11) - assert.Equal(t, tls11, version) - assert.NoError(t, err) - - version, err = TLSStringToTLSConfigVersion(TLS10) - assert.Equal(t, tls10, version) - assert.NoError(t, err) - - version, err = TLSStringToTLSConfigVersion("TLS" + TLS10) - assert.Equal(t, tls10, version) - assert.NoError(t, err) -} - -func TestShouldReturnZeroAndErrorOnInvalidTLSVersions(t *testing.T) { - version, err := TLSStringToTLSConfigVersion("TLS1.4") - assert.Error(t, err) - assert.Equal(t, uint16(0), version) - assert.EqualError(t, err, "supplied tls version isn't supported") - - version, err = TLSStringToTLSConfigVersion("SSL3.0") - assert.Error(t, err) - assert.Equal(t, uint16(0), version) - assert.EqualError(t, err, "supplied tls version isn't supported") -} - -func TestShouldReturnErrWhenX509DirectoryNotExist(t *testing.T) { - pool, warnings, errors := NewX509CertPool("/tmp/asdfzyxabc123/not/a/real/dir") - assert.NotNil(t, pool) - - if runtime.GOOS == windows { - require.Len(t, warnings, 1) - assert.EqualError(t, warnings[0], "could not load system certificate pool which may result in untrusted certificate issues: crypto/x509: system root pool is not available on Windows") - } else { - assert.Len(t, warnings, 0) - } - - require.Len(t, errors, 1) - - if runtime.GOOS == windows { - assert.EqualError(t, errors[0], "could not read certificates from directory open /tmp/asdfzyxabc123/not/a/real/dir: The system cannot find the path specified.") - } else { - assert.EqualError(t, errors[0], "could not read certificates from directory open /tmp/asdfzyxabc123/not/a/real/dir: no such file or directory") - } -} - -func TestShouldNotReturnErrWhenX509DirectoryExist(t *testing.T) { - pool, warnings, errors := NewX509CertPool("/tmp") - assert.NotNil(t, pool) - - if runtime.GOOS == windows { - require.Len(t, warnings, 1) - assert.EqualError(t, warnings[0], "could not load system certificate pool which may result in untrusted certificate issues: crypto/x509: system root pool is not available on Windows") - } else { - assert.Len(t, warnings, 0) - } - - assert.Len(t, errors, 0) -} - -func TestShouldReadCertsFromDirectoryButNotKeys(t *testing.T) { - pool, warnings, errors := NewX509CertPool("../suites/common/ssl/") - assert.NotNil(t, pool) - require.Len(t, errors, 1) - - if runtime.GOOS == "windows" { - require.Len(t, warnings, 1) - assert.EqualError(t, warnings[0], "could not load system certificate pool which may result in untrusted certificate issues: crypto/x509: system root pool is not available on Windows") - } else { - assert.Len(t, warnings, 0) - } - - assert.EqualError(t, errors[0], "could not import certificate key.pem") -} - -func TestShouldGenerateCertificateAndPersistIt(t *testing.T) { - testCases := []struct { - Name string - PrivateKeyBuilder PrivateKeyBuilder - }{ - { - Name: "P224", - PrivateKeyBuilder: ECDSAKeyBuilder{}.WithCurve(elliptic.P224()), - }, - { - Name: "P256", - PrivateKeyBuilder: ECDSAKeyBuilder{}.WithCurve(elliptic.P256()), - }, - { - Name: "P384", - PrivateKeyBuilder: ECDSAKeyBuilder{}.WithCurve(elliptic.P384()), - }, - { - Name: "P521", - PrivateKeyBuilder: ECDSAKeyBuilder{}.WithCurve(elliptic.P521()), - }, - { - Name: "Ed25519", - PrivateKeyBuilder: Ed25519KeyBuilder{}, - }, - { - Name: "RSA", - PrivateKeyBuilder: RSAKeyBuilder{keySizeInBits: 2048}, - }, - } - - for _, tc := range testCases { - t.Run(tc.Name, func(t *testing.T) { - certBytes, keyBytes, err := GenerateCertificate(tc.PrivateKeyBuilder, []string{"authelia.com", "example.org"}, time.Now(), 3*time.Hour, false) - require.NoError(t, err) - assert.True(t, len(certBytes) > 0) - assert.True(t, len(keyBytes) > 0) - }) - } -} diff --git a/internal/utils/const.go b/internal/utils/const.go index 649a4c63..add47e00 100644 --- a/internal/utils/const.go +++ b/internal/utils/const.go @@ -31,6 +31,36 @@ const ( unknown = "unknown" ) +// X.509 consts. +const ( + BlockTypeRSAPrivateKey = "RSA PRIVATE KEY" + BlockTypeRSAPublicKey = "RSA PUBLIC KEY" + BlockTypeECDSAPrivateKey = "EC PRIVATE KEY" + BlockTypePKCS8PrivateKey = "PRIVATE KEY" + BlockTypePKIXPublicKey = "PUBLIC KEY" + BlockTypeCertificate = "CERTIFICATE" + BlockTypeCertificateRequest = "CERTIFICATE REQUEST" + + KeyAlgorithmRSA = "RSA" + KeyAlgorithmECDSA = "ECDSA" + KeyAlgorithmEd25519 = "ED25519" + + HashAlgorithmSHA1 = "SHA1" + HashAlgorithmSHA256 = "SHA256" + HashAlgorithmSHA384 = "SHA384" + HashAlgorithmSHA512 = "SHA512" + + EllipticCurveP224 = "P224" + EllipticCurveP256 = "P256" + EllipticCurveP384 = "P384" + EllipticCurveP521 = "P521" + + EllipticCurveAltP224 = "P-224" + EllipticCurveAltP256 = "P-256" + EllipticCurveAltP384 = "P-384" + EllipticCurveAltP521 = "P-521" +) + const ( // Hour is an int based representation of the time unit. Hour = time.Minute * 60 //nolint:revive diff --git a/internal/utils/crypto.go b/internal/utils/crypto.go new file mode 100644 index 00000000..e2aa80ee --- /dev/null +++ b/internal/utils/crypto.go @@ -0,0 +1,582 @@ +package utils + +import ( + "bytes" + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rand" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "errors" + "fmt" + "math/big" + "net" + "os" + "path/filepath" + "strings" + "time" + + "github.com/authelia/authelia/v4/internal/configuration/schema" + "github.com/authelia/authelia/v4/internal/logging" +) + +// PEMBlockType represent an enum of the existing PEM block types. +type PEMBlockType int + +const ( + // Certificate block type. + Certificate PEMBlockType = iota + // PrivateKey block type. + PrivateKey +) + +// GenerateCertificate generate a certificate given a private key. RSA, Ed25519 and ECDSA are officially supported. +func GenerateCertificate(privateKeyBuilder PrivateKeyBuilder, hosts []string, validFrom time.Time, validFor time.Duration, isCA bool) ([]byte, []byte, error) { + privateKey, err := privateKeyBuilder.Build() + if err != nil { + return nil, nil, fmt.Errorf("unable to build private key: %w", err) + } + + notBefore := validFrom + notAfter := validFrom.Add(validFor) + + serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) + + serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) + if err != nil { + return nil, nil, fmt.Errorf("failed to generate serial number: %v", err) + } + + template := x509.Certificate{ + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{"Acme Co"}, + }, + NotBefore: notBefore, + NotAfter: notAfter, + + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, + BasicConstraintsValid: true, + } + + for _, h := range hosts { + if ip := net.ParseIP(h); ip != nil { + template.IPAddresses = append(template.IPAddresses, ip) + } else { + template.DNSNames = append(template.DNSNames, h) + } + } + + if isCA { + template.IsCA = true + template.KeyUsage |= x509.KeyUsageCertSign + } + + certDERBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, publicKey(privateKey), privateKey) + if err != nil { + return nil, nil, fmt.Errorf("failed to create certificate: %v", err) + } + + certPEMBytes, err := ConvertDERToPEM(certDERBytes, Certificate) + if err != nil { + return nil, nil, fmt.Errorf("failed to convert certificate in DER format into PEM: %v", err) + } + + keyDERBytes, err := x509.MarshalPKCS8PrivateKey(privateKey) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal private key: %v", err) + } + + keyPEMBytes, err := ConvertDERToPEM(keyDERBytes, PrivateKey) + if err != nil { + return nil, nil, fmt.Errorf("faile to convert certificate in DER format into PEM: %v", err) + } + + return certPEMBytes, keyPEMBytes, nil +} + +// ConvertDERToPEM convert certificate in DER format into PEM format. +func ConvertDERToPEM(der []byte, blockType PEMBlockType) ([]byte, error) { + var buf bytes.Buffer + + var blockTypeStr string + + switch blockType { + case Certificate: + blockTypeStr = "CERTIFICATE" + case PrivateKey: + blockTypeStr = "PRIVATE KEY" + default: + return nil, fmt.Errorf("unknown PEM block type %d", blockType) + } + + if err := pem.Encode(&buf, &pem.Block{Type: blockTypeStr, Bytes: der}); err != nil { + return nil, fmt.Errorf("failed to encode DER data into PEM: %v", err) + } + + return buf.Bytes(), nil +} + +func publicKey(privateKey interface{}) interface{} { + switch k := privateKey.(type) { + case *rsa.PrivateKey: + return &k.PublicKey + case *ecdsa.PrivateKey: + return &k.PublicKey + case ed25519.PrivateKey: + return k.Public().(ed25519.PublicKey) + default: + return nil + } +} + +// PrivateKeyBuilder interface for a private key builder. +type PrivateKeyBuilder interface { + Build() (interface{}, error) +} + +// RSAKeyBuilder builder of RSA private key. +type RSAKeyBuilder struct { + keySizeInBits int +} + +// WithKeySize configure the key size to use with RSA. +func (rkb RSAKeyBuilder) WithKeySize(bits int) RSAKeyBuilder { + rkb.keySizeInBits = bits + return rkb +} + +// Build a RSA private key. +func (rkb RSAKeyBuilder) Build() (interface{}, error) { + return rsa.GenerateKey(rand.Reader, rkb.keySizeInBits) +} + +// Ed25519KeyBuilder builder of Ed25519 private key. +type Ed25519KeyBuilder struct{} + +// Build an Ed25519 private key. +func (ekb Ed25519KeyBuilder) Build() (interface{}, error) { + _, priv, err := ed25519.GenerateKey(rand.Reader) + return priv, err +} + +// ECDSAKeyBuilder builder of ECDSA private key. +type ECDSAKeyBuilder struct { + curve elliptic.Curve +} + +// WithCurve configure the curve to use for the ECDSA private key. +func (ekb ECDSAKeyBuilder) WithCurve(curve elliptic.Curve) ECDSAKeyBuilder { + ekb.curve = curve + return ekb +} + +// Build an ECDSA private key. +func (ekb ECDSAKeyBuilder) Build() (interface{}, error) { + return ecdsa.GenerateKey(ekb.curve, rand.Reader) +} + +// ParseX509FromPEM parses PEM bytes and returns a PKCS key. +func ParseX509FromPEM(data []byte) (key interface{}, err error) { + block, _ := pem.Decode(data) + if block == nil { + return nil, errors.New("failed to parse PEM block containing the key") + } + + switch block.Type { + case BlockTypeRSAPrivateKey: + key, err = x509.ParsePKCS1PrivateKey(block.Bytes) + case BlockTypeECDSAPrivateKey: + key, err = x509.ParseECPrivateKey(block.Bytes) + case BlockTypePKCS8PrivateKey: + key, err = x509.ParsePKCS8PrivateKey(block.Bytes) + case BlockTypeRSAPublicKey: + key, err = x509.ParsePKCS1PublicKey(block.Bytes) + case BlockTypePKIXPublicKey: + key, err = x509.ParsePKIXPublicKey(block.Bytes) + case BlockTypeCertificate: + key, err = x509.ParseCertificate(block.Bytes) + default: + return nil, fmt.Errorf("unknown block type: %s", block.Type) + } + + if err != nil { + return nil, err + } + + return key, nil +} + +// CastX509AsCertificate converts an interface to an *x509.Certificate. +func CastX509AsCertificate(c interface{}) (certificate *x509.Certificate, ok bool) { + switch t := c.(type) { + case x509.Certificate: + return &t, true + case *x509.Certificate: + return t, true + default: + return nil, false + } +} + +// IsX509PrivateKey returns true if the provided interface is an rsa.PrivateKey, ecdsa.PrivateKey, or ed25519.PrivateKey. +func IsX509PrivateKey(i interface{}) bool { + switch i.(type) { + case rsa.PrivateKey, *rsa.PrivateKey, ecdsa.PrivateKey, *ecdsa.PrivateKey, ed25519.PrivateKey, *ed25519.PrivateKey: + return true + default: + return false + } +} + +// NewTLSConfig generates a tls.Config from a schema.TLSConfig and a x509.CertPool. +func NewTLSConfig(config *schema.TLSConfig, defaultMinVersion uint16, certPool *x509.CertPool) (tlsConfig *tls.Config) { + minVersion, err := TLSStringToTLSConfigVersion(config.MinimumVersion) + if err != nil { + minVersion = defaultMinVersion + } + + return &tls.Config{ + ServerName: config.ServerName, + InsecureSkipVerify: config.SkipVerify, //nolint:gosec // Informed choice by user. Off by default. + MinVersion: minVersion, + RootCAs: certPool, + } +} + +// NewX509CertPool generates a x509.CertPool from the system PKI and the directory specified. +func NewX509CertPool(directory string) (certPool *x509.CertPool, warnings []error, errors []error) { + certPool, err := x509.SystemCertPool() + if err != nil { + warnings = append(warnings, fmt.Errorf("could not load system certificate pool which may result in untrusted certificate issues: %v", err)) + certPool = x509.NewCertPool() + } + + logger := logging.Logger() + + logger.Tracef("Starting scan of directory %s for certificates", directory) + + if directory != "" { + certsFileInfo, err := os.ReadDir(directory) + if err != nil { + errors = append(errors, fmt.Errorf("could not read certificates from directory %v", err)) + } else { + for _, certFileInfo := range certsFileInfo { + nameLower := strings.ToLower(certFileInfo.Name()) + + if !certFileInfo.IsDir() && (strings.HasSuffix(nameLower, ".cer") || strings.HasSuffix(nameLower, ".crt") || strings.HasSuffix(nameLower, ".pem")) { + certPath := filepath.Join(directory, certFileInfo.Name()) + + logger.Tracef("Found possible cert %s, attempting to add it to the pool", certPath) + + certBytes, err := os.ReadFile(certPath) + if err != nil { + errors = append(errors, fmt.Errorf("could not read certificate %v", err)) + } else if ok := certPool.AppendCertsFromPEM(certBytes); !ok { + errors = append(errors, fmt.Errorf("could not import certificate %s", certFileInfo.Name())) + } + } + } + } + } + + logger.Tracef("Finished scan of directory %s for certificates", directory) + + return certPool, warnings, errors +} + +// TLSStringToTLSConfigVersion returns a go crypto/tls version for a tls.Config based on string input. +func TLSStringToTLSConfigVersion(input string) (version uint16, err error) { + switch strings.ToUpper(input) { + case "TLS1.3", TLS13: + return tls.VersionTLS13, nil + case "TLS1.2", TLS12: + return tls.VersionTLS12, nil + case "TLS1.1", TLS11: + return tls.VersionTLS11, nil + case "TLS1.0", TLS10: + return tls.VersionTLS10, nil + } + + return 0, ErrTLSVersionNotSupported +} + +// WriteCertificateBytesToPEM writes a certificate/csr to a file in the PEM format. +func WriteCertificateBytesToPEM(cert []byte, path string, csr bool) (err error) { + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return fmt.Errorf("failed to open %s for writing: %w", path, err) + } + + blockType := BlockTypeCertificate + if csr { + blockType = BlockTypeCertificateRequest + } + + if err = pem.Encode(out, &pem.Block{Bytes: cert, Type: blockType}); err != nil { + _ = out.Close() + + return err + } + + return out.Close() +} + +// WriteKeyToPEM writes a key that can be encoded as a PEM to a file in the PEM format. +func WriteKeyToPEM(key interface{}, path string, pkcs8 bool) (err error) { + pemBlock, err := PEMBlockFromX509Key(key, pkcs8) + if err != nil { + return err + } + + out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + return fmt.Errorf("failed to open %s for writing: %w", path, err) + } + + if err = pem.Encode(out, pemBlock); err != nil { + _ = out.Close() + + return err + } + + return out.Close() +} + +// PEMBlockFromX509Key turns a PublicKey or PrivateKey into a pem.Block. +func PEMBlockFromX509Key(key interface{}, pkcs8 bool) (pemBlock *pem.Block, err error) { + var ( + data []byte + blockType string + ) + + switch k := key.(type) { + case *rsa.PrivateKey: + if pkcs8 { + blockType = BlockTypePKCS8PrivateKey + data, err = x509.MarshalPKCS8PrivateKey(key) + + break + } + + blockType = BlockTypeRSAPrivateKey + data = x509.MarshalPKCS1PrivateKey(k) + case *ecdsa.PrivateKey: + if pkcs8 { + blockType = BlockTypePKCS8PrivateKey + data, err = x509.MarshalPKCS8PrivateKey(key) + + break + } + + blockType = BlockTypeECDSAPrivateKey + data, err = x509.MarshalECPrivateKey(k) + case ed25519.PrivateKey: + blockType = BlockTypePKCS8PrivateKey + data, err = x509.MarshalPKCS8PrivateKey(k) + case *rsa.PublicKey: + if pkcs8 { + blockType = BlockTypePKIXPublicKey + data, err = x509.MarshalPKIXPublicKey(key) + + break + } + + blockType = BlockTypeRSAPublicKey + data = x509.MarshalPKCS1PublicKey(k) + case *ecdsa.PublicKey, ed25519.PublicKey: + blockType = BlockTypePKIXPublicKey + data, err = x509.MarshalPKIXPublicKey(k) + default: + err = fmt.Errorf("failed to match key type: %T", k) + } + + if err != nil { + return nil, fmt.Errorf("failed to marshal key: %w", err) + } + + return &pem.Block{ + Type: blockType, + Bytes: data, + }, nil +} + +// KeySigAlgorithmFromString returns a x509.PublicKeyAlgorithm and x509.SignatureAlgorithm given a keyAlgorithm and signatureAlgorithm string. +func KeySigAlgorithmFromString(keyAlgorithm, signatureAlgorithm string) (keyAlg x509.PublicKeyAlgorithm, sigAlg x509.SignatureAlgorithm) { + keyAlg = PublicKeyAlgorithmFromString(keyAlgorithm) + + if keyAlg == x509.UnknownPublicKeyAlgorithm { + return x509.UnknownPublicKeyAlgorithm, x509.UnknownSignatureAlgorithm + } + + switch keyAlg { + case x509.RSA: + return keyAlg, RSASignatureAlgorithmFromString(signatureAlgorithm) + case x509.ECDSA: + return keyAlg, ECDSASignatureAlgorithmFromString(signatureAlgorithm) + case x509.Ed25519: + return keyAlg, x509.PureEd25519 + default: + return keyAlg, x509.UnknownSignatureAlgorithm + } +} + +// PublicKeyAlgorithmFromString returns a x509.PublicKeyAlgorithm given an appropriate string. +func PublicKeyAlgorithmFromString(algorithm string) (alg x509.PublicKeyAlgorithm) { + switch strings.ToUpper(algorithm) { + case KeyAlgorithmRSA: + return x509.RSA + case KeyAlgorithmECDSA: + return x509.ECDSA + case KeyAlgorithmEd25519: + return x509.Ed25519 + default: + return x509.UnknownPublicKeyAlgorithm + } +} + +// RSASignatureAlgorithmFromString returns a x509.SignatureAlgorithm for the RSA x509.PublicKeyAlgorithm given an +// algorithm string. +func RSASignatureAlgorithmFromString(algorithm string) (alg x509.SignatureAlgorithm) { + switch strings.ToUpper(algorithm) { + case HashAlgorithmSHA1: + return x509.SHA1WithRSA + case HashAlgorithmSHA256: + return x509.SHA256WithRSA + case HashAlgorithmSHA384: + return x509.SHA384WithRSA + case HashAlgorithmSHA512: + return x509.SHA512WithRSA + default: + return x509.UnknownSignatureAlgorithm + } +} + +// ECDSASignatureAlgorithmFromString returns a x509.SignatureAlgorithm for the ECDSA x509.PublicKeyAlgorithm given an +// algorithm string. +func ECDSASignatureAlgorithmFromString(algorithm string) (alg x509.SignatureAlgorithm) { + switch strings.ToUpper(algorithm) { + case HashAlgorithmSHA1: + return x509.ECDSAWithSHA1 + case HashAlgorithmSHA256: + return x509.ECDSAWithSHA256 + case HashAlgorithmSHA384: + return x509.ECDSAWithSHA384 + case HashAlgorithmSHA512: + return x509.ECDSAWithSHA512 + default: + return x509.UnknownSignatureAlgorithm + } +} + +// EllipticCurveFromString turns a string into an elliptic.Curve. +func EllipticCurveFromString(curveString string) (curve elliptic.Curve) { + switch strings.ToUpper(curveString) { + case EllipticCurveAltP224, EllipticCurveP224: + return elliptic.P224() + case EllipticCurveAltP256, EllipticCurveP256: + return elliptic.P256() + case EllipticCurveAltP384, EllipticCurveP384: + return elliptic.P384() + case EllipticCurveAltP521, EllipticCurveP521: + return elliptic.P521() + default: + return nil + } +} + +// PublicKeyFromPrivateKey returns a PublicKey when provided with a PrivateKey. +func PublicKeyFromPrivateKey(privateKey interface{}) (publicKey interface{}) { + switch k := privateKey.(type) { + case *rsa.PrivateKey: + return &k.PublicKey + case *ecdsa.PrivateKey: + return &k.PublicKey + case ed25519.PrivateKey: + return k.Public().(ed25519.PublicKey) + default: + return nil + } +} + +// X509ParseKeyUsage parses a list of key usages. If provided with an empty list returns a default of Key Encipherment +// and Digital Signature unless ca is true in which case it returns Cert Sign. +func X509ParseKeyUsage(keyUsages []string, ca bool) (keyUsage x509.KeyUsage) { + if len(keyUsages) == 0 { + keyUsage = x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature + if ca { + keyUsage |= x509.KeyUsageCertSign + } + + return keyUsage + } + + for _, keyUsageString := range keyUsages { + switch strings.ToLower(keyUsageString) { + case "digitalsignature", "digital_signature": + keyUsage |= x509.KeyUsageDigitalSignature + case "keyencipherment", "key_encipherment": + keyUsage |= x509.KeyUsageKeyEncipherment + case "dataencipherment", "data_encipherment": + keyUsage |= x509.KeyUsageDataEncipherment + case "keyagreement", "key_agreement": + keyUsage |= x509.KeyUsageKeyAgreement + case "certsign", "cert_sign", "certificatesign", "certificate_sign": + keyUsage |= x509.KeyUsageCertSign + case "crlsign", "crl_sign": + keyUsage |= x509.KeyUsageCRLSign + case "encipheronly", "encipher_only": + keyUsage |= x509.KeyUsageEncipherOnly + case "decipheronly", "decipher_only": + keyUsage |= x509.KeyUsageDecipherOnly + } + } + + return keyUsage +} + +// X509ParseExtendedKeyUsage parses a list of extended key usages. If provided with an empty list returns a default of +// Server Auth unless ca is true in which case it returns a default of Any. +func X509ParseExtendedKeyUsage(extKeyUsages []string, ca bool) (extKeyUsage []x509.ExtKeyUsage) { + if len(extKeyUsages) == 0 { + if ca { + extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny} + } else { + extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} + } + + return extKeyUsage + } + +loop: + for _, extKeyUsageString := range extKeyUsages { + switch strings.ToLower(extKeyUsageString) { + case "any": + extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny} + break loop + case "serverauth", "server_auth": + extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageServerAuth) + case "clientauth", "client_auth": + extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageClientAuth) + case "codesigning", "code_signing": + extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageCodeSigning) + case "emailprotection", "email_protection": + extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageEmailProtection) + case "ipsecendsystem", "ipsec_endsystem", "ipsec_end_system": + extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageIPSECEndSystem) + case "ipsectunnel", "ipsec_tunnel": + extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageIPSECTunnel) + case "ipsecuser", "ipsec_user": + extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageIPSECUser) + case "ocspsigning", "ocsp_signing": + extKeyUsage = append(extKeyUsage, x509.ExtKeyUsageOCSPSigning) + } + } + + return extKeyUsage +} diff --git a/internal/utils/crypto_test.go b/internal/utils/crypto_test.go new file mode 100644 index 00000000..9d4adb9f --- /dev/null +++ b/internal/utils/crypto_test.go @@ -0,0 +1,538 @@ +package utils + +import ( + "crypto/ecdsa" + "crypto/ed25519" + "crypto/elliptic" + "crypto/rsa" + "crypto/tls" + "crypto/x509" + "runtime" + "strings" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/authelia/authelia/v4/internal/configuration/schema" +) + +func TestShouldSetupDefaultTLSMinVersionOnErr(t *testing.T) { + schemaTLSConfig := &schema.TLSConfig{ + MinimumVersion: "NotAVersion", + ServerName: "golang.org", + SkipVerify: true, + } + + tlsConfig := NewTLSConfig(schemaTLSConfig, tls.VersionTLS12, nil) + + assert.Equal(t, uint16(tls.VersionTLS12), tlsConfig.MinVersion) + assert.Equal(t, "golang.org", tlsConfig.ServerName) + assert.True(t, tlsConfig.InsecureSkipVerify) +} + +func TestShouldReturnCorrectTLSVersions(t *testing.T) { + tls13 := uint16(tls.VersionTLS13) + tls12 := uint16(tls.VersionTLS12) + tls11 := uint16(tls.VersionTLS11) + tls10 := uint16(tls.VersionTLS10) + + version, err := TLSStringToTLSConfigVersion(TLS13) + assert.Equal(t, tls13, version) + assert.NoError(t, err) + + version, err = TLSStringToTLSConfigVersion("TLS" + TLS13) + assert.Equal(t, tls13, version) + assert.NoError(t, err) + + version, err = TLSStringToTLSConfigVersion(TLS12) + assert.Equal(t, tls12, version) + assert.NoError(t, err) + + version, err = TLSStringToTLSConfigVersion("TLS" + TLS12) + assert.Equal(t, tls12, version) + assert.NoError(t, err) + + version, err = TLSStringToTLSConfigVersion(TLS11) + assert.Equal(t, tls11, version) + assert.NoError(t, err) + + version, err = TLSStringToTLSConfigVersion("TLS" + TLS11) + assert.Equal(t, tls11, version) + assert.NoError(t, err) + + version, err = TLSStringToTLSConfigVersion(TLS10) + assert.Equal(t, tls10, version) + assert.NoError(t, err) + + version, err = TLSStringToTLSConfigVersion("TLS" + TLS10) + assert.Equal(t, tls10, version) + assert.NoError(t, err) +} + +func TestShouldReturnZeroAndErrorOnInvalidTLSVersions(t *testing.T) { + version, err := TLSStringToTLSConfigVersion("TLS1.4") + assert.Error(t, err) + assert.Equal(t, uint16(0), version) + assert.EqualError(t, err, "supplied tls version isn't supported") + + version, err = TLSStringToTLSConfigVersion("SSL3.0") + assert.Error(t, err) + assert.Equal(t, uint16(0), version) + assert.EqualError(t, err, "supplied tls version isn't supported") +} + +func TestShouldReturnErrWhenX509DirectoryNotExist(t *testing.T) { + pool, warnings, errors := NewX509CertPool("/tmp/asdfzyxabc123/not/a/real/dir") + assert.NotNil(t, pool) + + if runtime.GOOS == windows { + require.Len(t, warnings, 1) + assert.EqualError(t, warnings[0], "could not load system certificate pool which may result in untrusted certificate issues: crypto/x509: system root pool is not available on Windows") + } else { + assert.Len(t, warnings, 0) + } + + require.Len(t, errors, 1) + + if runtime.GOOS == windows { + assert.EqualError(t, errors[0], "could not read certificates from directory open /tmp/asdfzyxabc123/not/a/real/dir: The system cannot find the path specified.") + } else { + assert.EqualError(t, errors[0], "could not read certificates from directory open /tmp/asdfzyxabc123/not/a/real/dir: no such file or directory") + } +} + +func TestShouldNotReturnErrWhenX509DirectoryExist(t *testing.T) { + pool, warnings, errors := NewX509CertPool("/tmp") + assert.NotNil(t, pool) + + if runtime.GOOS == windows { + require.Len(t, warnings, 1) + assert.EqualError(t, warnings[0], "could not load system certificate pool which may result in untrusted certificate issues: crypto/x509: system root pool is not available on Windows") + } else { + assert.Len(t, warnings, 0) + } + + assert.Len(t, errors, 0) +} + +func TestShouldReadCertsFromDirectoryButNotKeys(t *testing.T) { + pool, warnings, errors := NewX509CertPool("../suites/common/ssl/") + assert.NotNil(t, pool) + require.Len(t, errors, 1) + + if runtime.GOOS == "windows" { + require.Len(t, warnings, 1) + assert.EqualError(t, warnings[0], "could not load system certificate pool which may result in untrusted certificate issues: crypto/x509: system root pool is not available on Windows") + } else { + assert.Len(t, warnings, 0) + } + + assert.EqualError(t, errors[0], "could not import certificate key.pem") +} + +func TestShouldGenerateCertificateAndPersistIt(t *testing.T) { + testCases := []struct { + Name string + PrivateKeyBuilder PrivateKeyBuilder + }{ + { + Name: "P224", + PrivateKeyBuilder: ECDSAKeyBuilder{}.WithCurve(elliptic.P224()), + }, + { + Name: "P256", + PrivateKeyBuilder: ECDSAKeyBuilder{}.WithCurve(elliptic.P256()), + }, + { + Name: "P384", + PrivateKeyBuilder: ECDSAKeyBuilder{}.WithCurve(elliptic.P384()), + }, + { + Name: "P521", + PrivateKeyBuilder: ECDSAKeyBuilder{}.WithCurve(elliptic.P521()), + }, + { + Name: "Ed25519", + PrivateKeyBuilder: Ed25519KeyBuilder{}, + }, + { + Name: "RSA", + PrivateKeyBuilder: RSAKeyBuilder{keySizeInBits: 2048}, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + certBytes, keyBytes, err := GenerateCertificate(tc.PrivateKeyBuilder, []string{"authelia.com", "example.org"}, time.Now(), 3*time.Hour, false) + require.NoError(t, err) + assert.True(t, len(certBytes) > 0) + assert.True(t, len(keyBytes) > 0) + }) + } +} + +func TestShouldParseKeySigAlgorithm(t *testing.T) { + testCases := []struct { + Name string + InputKey, InputSig string + ExpectedKeyAlg x509.PublicKeyAlgorithm + ExpectedSigAlg x509.SignatureAlgorithm + }{ + { + Name: "ShouldNotParseInvalidKeyAlg", + InputKey: "DDD", + InputSig: "SHA1", + ExpectedKeyAlg: x509.UnknownPublicKeyAlgorithm, + ExpectedSigAlg: x509.UnknownSignatureAlgorithm, + }, + { + Name: "ShouldParseKeyRSASigSHA1", + InputKey: "RSA", + InputSig: "SHA1", + ExpectedKeyAlg: x509.RSA, + ExpectedSigAlg: x509.SHA1WithRSA, + }, + { + Name: "ShouldParseKeyRSASigSHA256", + InputKey: "RSA", + InputSig: "SHA256", + ExpectedKeyAlg: x509.RSA, + ExpectedSigAlg: x509.SHA256WithRSA, + }, + { + Name: "ShouldParseKeyRSASigSHA384", + InputKey: "RSA", + InputSig: "SHA384", + ExpectedKeyAlg: x509.RSA, + ExpectedSigAlg: x509.SHA384WithRSA, + }, + { + Name: "ShouldParseKeyRSASigSHA512", + InputKey: "RSA", + InputSig: "SHA512", + ExpectedKeyAlg: x509.RSA, + ExpectedSigAlg: x509.SHA512WithRSA, + }, + { + Name: "ShouldNotParseKeyRSASigInvalid", + InputKey: "RSA", + InputSig: "INVALID", + ExpectedKeyAlg: x509.RSA, + ExpectedSigAlg: x509.UnknownSignatureAlgorithm, + }, + { + Name: "ShouldParseKeyECDSASigSHA1", + InputKey: "ECDSA", + InputSig: "SHA1", + ExpectedKeyAlg: x509.ECDSA, + ExpectedSigAlg: x509.ECDSAWithSHA1, + }, + { + Name: "ShouldParseKeyECDSASigSHA256", + InputKey: "ECDSA", + InputSig: "SHA256", + ExpectedKeyAlg: x509.ECDSA, + ExpectedSigAlg: x509.ECDSAWithSHA256, + }, + { + Name: "ShouldParseKeyECDSASigSHA384", + InputKey: "ECDSA", + InputSig: "SHA384", + ExpectedKeyAlg: x509.ECDSA, + ExpectedSigAlg: x509.ECDSAWithSHA384, + }, + { + Name: "ShouldParseKeyECDSASigSHA512", + InputKey: "ECDSA", + InputSig: "SHA512", + ExpectedKeyAlg: x509.ECDSA, + ExpectedSigAlg: x509.ECDSAWithSHA512, + }, + { + Name: "ShouldNotParseKeyECDSASigInvalid", + InputKey: "ECDSA", + InputSig: "INVALID", + ExpectedKeyAlg: x509.ECDSA, + ExpectedSigAlg: x509.UnknownSignatureAlgorithm, + }, + { + Name: "ShouldParseKeyEd25519SigSHA1", + InputKey: "ED25519", + InputSig: "SHA1", + ExpectedKeyAlg: x509.Ed25519, + ExpectedSigAlg: x509.PureEd25519, + }, + { + Name: "ShouldParseKeyEd25519SigSHA256", + InputKey: "ED25519", + InputSig: "SHA256", + ExpectedKeyAlg: x509.Ed25519, + ExpectedSigAlg: x509.PureEd25519, + }, + { + Name: "ShouldParseKeyEd25519SigSHA384", + InputKey: "ED25519", + InputSig: "SHA384", + ExpectedKeyAlg: x509.Ed25519, + ExpectedSigAlg: x509.PureEd25519, + }, + { + Name: "ShouldParseKeyEd25519SigSHA512", + InputKey: "ED25519", + InputSig: "SHA512", + ExpectedKeyAlg: x509.Ed25519, + ExpectedSigAlg: x509.PureEd25519, + }, + { + Name: "ShouldParseKeyEd25519SigInvalid", + InputKey: "ED25519", + InputSig: "INVALID", + ExpectedKeyAlg: x509.Ed25519, + ExpectedSigAlg: x509.PureEd25519, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + actualKey, actualSig := KeySigAlgorithmFromString(tc.InputKey, tc.InputSig) + actualKeyLower, actualSigLower := KeySigAlgorithmFromString(strings.ToLower(tc.InputKey), strings.ToLower(tc.InputSig)) + + assert.Equal(t, tc.ExpectedKeyAlg, actualKey) + assert.Equal(t, tc.ExpectedSigAlg, actualSig) + assert.Equal(t, tc.ExpectedKeyAlg, actualKeyLower) + assert.Equal(t, tc.ExpectedSigAlg, actualSigLower) + }) + } +} + +func TestShouldParseCurves(t *testing.T) { + testCases := []struct { + Name string + Input string + Expected elliptic.Curve + }{ + { + Name: "P224-Standard", + Input: "P224", + Expected: elliptic.P224(), + }, + { + Name: "P224-Lowercase", + Input: "p224", + Expected: elliptic.P224(), + }, + { + Name: "P224-Hyphenated", + Input: "P-224", + Expected: elliptic.P224(), + }, + { + Name: "P256-Standard", + Input: "P256", + Expected: elliptic.P256(), + }, + { + Name: "P256-Lowercase", + Input: "p256", + Expected: elliptic.P256(), + }, + { + Name: "P256-Hyphenated", + Input: "P-256", + Expected: elliptic.P256(), + }, + { + Name: "P384-Standard", + Input: "P384", + Expected: elliptic.P384(), + }, + { + Name: "P384-Lowercase", + Input: "p384", + Expected: elliptic.P384(), + }, + { + Name: "P384-Hyphenated", + Input: "P-384", + Expected: elliptic.P384(), + }, + { + Name: "P521-Standard", + Input: "P521", + Expected: elliptic.P521(), + }, + { + Name: "P521-Lowercase", + Input: "p521", + Expected: elliptic.P521(), + }, + { + Name: "P521-Hyphenated", + Input: "P-521", + Expected: elliptic.P521(), + }, + { + Name: "Invalid", + Input: "521", + Expected: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + actual := EllipticCurveFromString(tc.Input) + + assert.Equal(t, tc.Expected, actual) + }) + } +} + +func testMustBuildPrivateKey(b PrivateKeyBuilder) interface{} { + k, err := b.Build() + if err != nil { + panic(err) + } + + return k +} + +func TestPublicKeyFromPrivateKey(t *testing.T) { + testCases := []struct { + Name string + PrivateKey interface{} + Expected interface{} + }{ + { + Name: "RSA2048", + PrivateKey: testMustBuildPrivateKey(RSAKeyBuilder{}.WithKeySize(512)), + Expected: &rsa.PublicKey{}, + }, + { + Name: "ECDSA-P256", + PrivateKey: testMustBuildPrivateKey(ECDSAKeyBuilder{}.WithCurve(elliptic.P256())), + Expected: &ecdsa.PublicKey{}, + }, + { + Name: "Ed25519", + PrivateKey: testMustBuildPrivateKey(Ed25519KeyBuilder{}), + Expected: ed25519.PublicKey{}, + }, + { + Name: "Invalid", + PrivateKey: 8, + Expected: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.Name, func(t *testing.T) { + actual := PublicKeyFromPrivateKey(tc.PrivateKey) + + if tc.Expected == nil { + assert.Nil(t, actual) + } else { + assert.IsType(t, tc.Expected, actual) + } + }) + } +} + +func TestX509ParseKeyUsage(t *testing.T) { + testCases := []struct { + name string + have [][]string + ca bool + expected x509.KeyUsage + }{ + { + "ShouldParseDefault", nil, false, x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + }, + { + "ShouldParseDefaultCA", nil, true, x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + }, + { + "ShouldParseDigitalSignature", [][]string{{"digital_signature"}, {"Digital_Signature"}, {"digitalsignature"}, {"digitalSignature"}}, false, x509.KeyUsageDigitalSignature, + }, + { + "ShouldParseKeyEncipherment", [][]string{{"key_encipherment"}, {"Key_Encipherment"}, {"keyencipherment"}, {"keyEncipherment"}}, false, x509.KeyUsageKeyEncipherment, + }, + { + "ShouldParseDataEncipherment", [][]string{{"data_encipherment"}, {"Data_Encipherment"}, {"dataencipherment"}, {"dataEncipherment"}}, false, x509.KeyUsageDataEncipherment, + }, + { + "ShouldParseKeyAgreement", [][]string{{"key_agreement"}, {"Key_Agreement"}, {"keyagreement"}, {"keyAgreement"}}, false, x509.KeyUsageKeyAgreement, + }, + { + "ShouldParseCertSign", [][]string{{"cert_sign"}, {"Cert_Sign"}, {"certsign"}, {"certSign"}, {"certificate_sign"}, {"Certificate_Sign"}, {"certificatesign"}, {"certificateSign"}}, false, x509.KeyUsageCertSign, + }, + { + "ShouldParseCRLSign", [][]string{{"crl_sign"}, {"CRL_Sign"}, {"crlsign"}, {"CRLSign"}}, false, x509.KeyUsageCRLSign, + }, + { + "ShouldParseEncipherOnly", [][]string{{"encipher_only"}, {"Encipher_Only"}, {"encipheronly"}, {"encipherOnly"}}, false, x509.KeyUsageEncipherOnly, + }, + { + "ShouldParseDecipherOnly", [][]string{{"decipher_only"}, {"Decipher_Only"}, {"decipheronly"}, {"decipherOnly"}}, false, x509.KeyUsageDecipherOnly, + }, + { + "ShouldParseMulti", [][]string{{"digitalSignature", "keyEncipherment", "dataEncipherment", "certSign", "crlSign"}}, false, x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageDataEncipherment | x509.KeyUsageCertSign | x509.KeyUsageCRLSign, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if len(tc.have) == 0 { + actual := X509ParseKeyUsage(nil, tc.ca) + + assert.Equal(t, tc.expected, actual) + } + for _, have := range tc.have { + t.Run(strings.Join(have, ","), func(t *testing.T) { + actual := X509ParseKeyUsage(have, tc.ca) + + assert.Equal(t, tc.expected, actual) + }) + } + }) + } +} + +func TestX509ParseExtendedKeyUsage(t *testing.T) { + testCases := []struct { + name string + have [][]string + ca bool + expected []x509.ExtKeyUsage + }{ + {"ShouldParseDefault", nil, false, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}}, + {"ShouldParseDefaultCA", nil, true, []x509.ExtKeyUsage{x509.ExtKeyUsageAny}}, + {"ShouldParseAny", [][]string{{"any"}, {"Any"}, {"any", "server_auth"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageAny}}, + {"ShouldParseServerAuth", [][]string{{"server_auth"}, {"Server_Auth"}, {"serverauth"}, {"serverAuth"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}}, + {"ShouldParseClientAuth", [][]string{{"client_auth"}, {"Client_Auth"}, {"clientauth"}, {"clientAuth"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}}, + {"ShouldParseCodeSigning", [][]string{{"code_signing"}, {"Code_Signing"}, {"codesigning"}, {"codeSigning"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageCodeSigning}}, + {"ShouldParseEmailProtection", [][]string{{"email_protection"}, {"Email_Protection"}, {"emailprotection"}, {"emailProtection"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageEmailProtection}}, + {"ShouldParseIPSECEndSystem", [][]string{{"ipsec_endsystem"}, {"IPSEC_Endsystem"}, {"ipsec_end_system"}, {"IPSEC_End_System"}, {"ipsecendsystem"}, {"ipsecEndSystem"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageIPSECEndSystem}}, + {"ShouldParseIPSECTunnel", [][]string{{"ipsec_tunnel"}, {"IPSEC_Tunnel"}, {"ipsectunnel"}, {"ipsecTunnel"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageIPSECTunnel}}, + {"ShouldParseIPSECUser", [][]string{{"ipsec_user"}, {"IPSEC_User"}, {"ipsecuser"}, {"ipsecUser"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageIPSECUser}}, + {"ShouldParseOCSPSigning", [][]string{{"ocsp_signing"}, {"OCSP_Signing"}, {"ocspsigning"}, {"ocspSigning"}}, false, []x509.ExtKeyUsage{x509.ExtKeyUsageOCSPSigning}}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if len(tc.have) == 0 { + actual := X509ParseExtendedKeyUsage(nil, tc.ca) + + assert.Equal(t, tc.expected, actual) + } + for _, have := range tc.have { + t.Run(strings.Join(have, ","), func(t *testing.T) { + actual := X509ParseExtendedKeyUsage(have, tc.ca) + + assert.Equal(t, tc.expected, actual) + }) + } + }) + } +} diff --git a/internal/utils/rsa.go b/internal/utils/rsa.go deleted file mode 100644 index 7dd2695f..00000000 --- a/internal/utils/rsa.go +++ /dev/null @@ -1,83 +0,0 @@ -package utils - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" -) - -// GenerateRsaKeyPair generate an RSA key pair. -// bits can be 2048 or 4096. -func GenerateRsaKeyPair(bits int) (*rsa.PrivateKey, *rsa.PublicKey) { - privkey, _ := rsa.GenerateKey(rand.Reader, bits) - return privkey, &privkey.PublicKey -} - -// ExportRsaPrivateKeyAsPemStr marshal a rsa private key into PEM string. -func ExportRsaPrivateKeyAsPemStr(privkey *rsa.PrivateKey) string { - privkeyBytes := x509.MarshalPKCS1PrivateKey(privkey) - privkeyPem := pem.EncodeToMemory( - &pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: privkeyBytes, - }, - ) - - return string(privkeyPem) -} - -// ParseRsaPrivateKeyFromPemStr parse a RSA private key from PEM string. -func ParseRsaPrivateKeyFromPemStr(privPEM string) (*rsa.PrivateKey, error) { - block, _ := pem.Decode([]byte(privPEM)) - if block == nil { - return nil, errors.New("failed to parse PEM block containing the key") - } - - priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - return nil, err - } - - return priv, nil -} - -// ExportRsaPublicKeyAsPemStr marshal a RSA public into a PEM string. -func ExportRsaPublicKeyAsPemStr(pubkey *rsa.PublicKey) (string, error) { - pubkeyBytes, err := x509.MarshalPKIXPublicKey(pubkey) - if err != nil { - return "", err - } - - pubkeyPem := pem.EncodeToMemory( - &pem.Block{ - Type: "RSA PUBLIC KEY", - Bytes: pubkeyBytes, - }, - ) - - return string(pubkeyPem), nil -} - -// ParseRsaPublicKeyFromPemStr parse RSA public key from a PEM string. -func ParseRsaPublicKeyFromPemStr(pubPEM string) (*rsa.PublicKey, error) { - block, _ := pem.Decode([]byte(pubPEM)) - if block == nil { - return nil, errors.New("failed to parse PEM block containing the key") - } - - pub, err := x509.ParsePKIXPublicKey(block.Bytes) - if err != nil { - return nil, err - } - - switch pub := pub.(type) { - case *rsa.PublicKey: - return pub, nil - default: - break // fall through. - } - - return nil, errors.New("key type is not RSA") -}