diff --git a/docs/content/en/configuration/miscellaneous/guides.md b/docs/content/en/configuration/miscellaneous/guides.md index 64b5a4023..34311d11e 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 6cbd0a1e2..c6b867ddb 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 02b76ddeb..3795ca9f8 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 9f67ef67c..69eab9aad 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 8af830638..82101c373 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 b065e6144..7445e9f8c 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 59b40514f..725ac1cae 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 470c325eb..04a621f04 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 f9f82f88d..debd4e60e 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 f9fd43925..25402c2ea 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 d5900faba..b18caa9b6 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 1ca489024..4ed27faa2 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 f06f7d773..f765e1a7c 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 959f7c64b..506090bd9 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 5179e329e..62a98ca28 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 462cb2d80..685f7c1a2 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 2ff57852a..175b321b7 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 00bf92dcc..43c975615 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 864c0afc5..3f48251c4 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 796797888..f60f066a8 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 91c820afc..64a576b24 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 8fc11527a..c8236e2c1 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 e12a7c54b..80196b3f5 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 353b7a1ab..8707c1c67 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 b7a4b68eb..b39dd3950 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 b95dbbc6c..c4ef49385 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 6f6890c2d..0dc98d8c3 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 cd18eb486..3fa26216c 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 684c353c1..8e1c72131 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 40107937f..fdcbd6f36 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 cab5550d1..a0a99bcd6 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 faa84356e..ef16df7ae 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 012ba9930..aab5ea421 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 5bfeff7b5..d9f727d8f 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 d525b6585..8a642248a 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 fbfba5fe5..622134ab3 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 20c17b546..9af596177 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 8583c53ff..000000000 --- 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 672549c5f..000000000 --- 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 000000000..cb61ce8ae --- /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 000000000..66fbf3fb9 --- /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 000000000..6e0d92080 --- /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 000000000..dcbe98723 --- /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 000000000..81889a921 --- /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 000000000..8dced8f32 --- /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 000000000..56dc593fd --- /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 000000000..5dea9ada3 --- /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 000000000..14e28a1e4 --- /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 000000000..3dfc1aa3b --- /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 000000000..fa2f5eec3 --- /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 000000000..cda36b0d1 --- /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 000000000..51fd7eea6 --- /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 000000000..84b9c4ab5 --- /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 000000000..e7ca06d4a --- /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 000000000..6ee450a53 --- /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 000000000..c47386dd2 --- /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 000000000..b806a62a7 --- /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 cd66e6de8..9c49414e1 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 ea3b6469b..000000000 --- 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 9b80d345c..000000000 --- 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 0423b9b68..b2fabe4cb 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 a119ec7f4..8555e7295 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 f6fb2d41e..0a7f6b3d2 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 96c225e87..2660c35a7 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 383f29757..1819eacc5 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 07ee94ffc..bc1997334 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 c1b5af4ea..557ecccf7 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 b1d8f0481..817d0c4f0 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 075ef56a2..e1774f473 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 bd3d19fb0..59a86b318 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 08a1a7cd8..33d7b3b93 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 31ff94c2f..386005e61 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 c5c853ece..5bbf11a4d 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 7ca3f171c..dcb8879d6 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 325a1c7b4..64e03a02e 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 5f6fd17c8..fb08f0b49 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 cdd838cd2..3fbcb27fc 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 caf7c97a6..af8669116 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 6d0becae9..3c4397c96 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 1d186d978..49ba40fce 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 23346f7c4..f925807fc 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 a7a4a9842..b90febcce 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 9a0dc65dd..56c211ddf 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 6a0bb286b..000000000 --- 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 008da12ed..ad9cc1879 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 000000000..0035a3d23 --- /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 000000000..96e23f673 --- /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 52face48a..071c03422 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 4b8983321..000000000 --- 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 8460efbf7..946526252 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 74edcf016..b236e1dd9 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 810806ec2..e2efc5623 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 bc7d2952a..000000000 --- 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 918678fe8..000000000 --- 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 649a4c639..add47e00a 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 000000000..e2aa80ee7 --- /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 000000000..9d4adb9f5 --- /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 7dd2695fa..000000000 --- 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") -}