diff --git a/cmd/authelia-gen/cmd_docs_cli.go b/cmd/authelia-gen/cmd_docs_cli.go index 0bade8795..5e137bff3 100644 --- a/cmd/authelia-gen/cmd_docs_cli.go +++ b/cmd/authelia-gen/cmd_docs_cli.go @@ -108,8 +108,9 @@ func genCLIDocWriteIndex(path, name string) (err error) { func prepend(input string) string { now := time.Now() - pathz := strings.Split(strings.Replace(input, ".md", "", 1), "\\") - parts := strings.Split(pathz[len(pathz)-1], "_") + _, filename := filepath.Split(strings.Replace(input, ".md", "", 1)) + + parts := strings.Split(filename, "_") cmd := parts[0] diff --git a/cmd/authelia-scripts/cmd/bootstrap.go b/cmd/authelia-scripts/cmd/bootstrap.go index 82cd8a0c0..1dc26e749 100644 --- a/cmd/authelia-scripts/cmd/bootstrap.go +++ b/cmd/authelia-scripts/cmd/bootstrap.go @@ -64,7 +64,7 @@ func cmdBootstrapRun(_ *cobra.Command, _ []string) { fmt.Println() bootstrapPrintln("Run 'authelia-scripts suites setup Standalone' to start Authelia and visit https://home.example.com:8080.") - bootstrapPrintln("More details at https://github.com/authelia/authelia/blob/master/docs/getting-started.md") + bootstrapPrintln("More details at https://www.authelia.com/contributing/development/build-and-test/") } var hostEntries = []HostEntry{ diff --git a/docs/content/en/configuration/prologue/common.md b/docs/content/en/configuration/prologue/common.md index f250ea251..2c549f75c 100644 --- a/docs/content/en/configuration/prologue/common.md +++ b/docs/content/en/configuration/prologue/common.md @@ -35,10 +35,18 @@ The way this format works is you can either configure an integer or a string in supply an integer, it is considered a representation of seconds. If you supply a string, it parses the string in blocks of quantities and units (number followed by a unit letter). For example `5h` indicates a quantity of 5 units of `h`. +The following is ignored: + - all spaces + - leading zeros + While you can use multiple of these blocks in combination, we suggest keeping it simple and use a single value. ### Unit Legend +#### Short Units + +These values have been available for a long time. + | Unit | Associated Letter | |:-------:|:-----------------:| | Years | y | @@ -49,6 +57,21 @@ While you can use multiple of these blocks in combination, we suggest keeping it | Minutes | m | | Seconds | s | +#### Long Units + +These values are more human readable but have only been available since v4.38.0. + +| Unit | Human Readable Long Unit | +|:------------:|:-----------------------------:| +| Years | `year`, `years` | +| Months | `month`, `months` | +| Weeks | `week`, `weeks` | +| Days | `day`, `days` | +| Hours | `hour`, `hours` | +| Minutes | `minute`, `minutes` | +| Seconds | `second`, `seconds` | +| Milliseconds | `millisecond`, `milliseconds` | + ### Examples | Desired Value | Configuration Examples | diff --git a/docs/content/en/integration/proxies/envoy.md b/docs/content/en/integration/proxies/envoy.md index edb2a1eb3..76ce52e12 100644 --- a/docs/content/en/integration/proxies/envoy.md +++ b/docs/content/en/integration/proxies/envoy.md @@ -168,6 +168,13 @@ static_resources: - name: envoy.filters.http.ext_authz typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + transport_api_version: v3 + allowed_headers: + patterns: + - exact: authorization + - exact: proxy-authorization + - exact: accept + - exact: cookie http_service: path_prefix: /api/authz/ext-authz/ server_uri: @@ -208,9 +215,9 @@ static_resources: clusters: - name: nextcloud connect_timeout: 0.25s - type: LOGICAL_DNS - dns_lookup_family: V4_ONLY - lb_policy: ROUND_ROBIN + type: logical_dns + dns_lookup_family: v4_only + lb_policy: round_robin load_assignment: cluster_name: nextcloud endpoints: @@ -222,9 +229,9 @@ static_resources: port_value: 80 - name: authelia connect_timeout: 0.25s - type: LOGICAL_DNS - dns_lookup_family: V4_ONLY - lb_policy: ROUND_ROBIN + type: logical_dns + dns_lookup_family: v4_only + lb_policy: round_robin load_assignment: cluster_name: authelia endpoints: @@ -234,6 +241,17 @@ static_resources: socket_address: address: authelia port_value: 9091 +layered_runtime: + layers: + - name: static_layer_0 + static_layer: + envoy: + resource_limits: + listener: + example_listener_name: + connection_limit: 10000 + overload: + global_downstream_max_connections: 50000 ``` {{< /details >}} diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md index 13fc82481..324c96ed2 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_generate.md @@ -35,28 +35,31 @@ authelia crypto certificate ecdsa generate --help ### Options ``` - --ca create the certificate as a certificate authority certificate - -n, --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 + --bundle enables generating the certificate bundle if the --path.ca flag is set + --ca create the certificate as a certificate authority certificate + -n, --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 string duration of time the certificate is valid for (default "1y") + --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.certificate-bundle string name of the file to export the certificate bundle data to when the --bundle flag is set (default "public.bundle.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-after string latest date and time the certificate is considered valid in various formats + --not-before string earliest date and time the certificate is considered valid in various formats (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 ``` ### Options inherited from parent commands diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md index 271da38eb..093cff375 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ecdsa_request.md @@ -39,12 +39,13 @@ authelia crypto certificate ecdsa request --help --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) + --duration string duration of time the certificate is valid for (default "1y") --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) + --not-after string latest date and time the certificate is considered valid in various formats + --not-before string earliest date and time the certificate is considered valid in various formats (default is now) -o, --organization strings certificate organization (default [Authelia]) --organizational-unit strings certificate organizational unit -p, --postcode strings certificate postcode diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md index 44e806357..7afaf5a9b 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_generate.md @@ -35,27 +35,30 @@ authelia crypto certificate ed25519 request --help ### Options ``` - --ca create the certificate as a certificate authority certificate - -n, --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 + --bundle enables generating the certificate bundle if the --path.ca flag is set + --ca create the certificate as a certificate authority certificate + -n, --common-name string certificate common name + --country strings certificate country + -d, --directory string directory where the generated keys, certificates, etc will be stored + --duration string duration of time the certificate is valid for (default "1y") + --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.certificate-bundle string name of the file to export the certificate bundle data to when the --bundle flag is set (default "public.bundle.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-after string latest date and time the certificate is considered valid in various formats + --not-before string earliest date and time the certificate is considered valid in various formats (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 ``` ### Options inherited from parent commands diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md index f0f3a5f8d..66d687d98 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_ed25519_request.md @@ -38,12 +38,13 @@ authelia crypto certificate ed25519 request --help -n, --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) + --duration string duration of time the certificate is valid for (default "1y") --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) + --not-after string latest date and time the certificate is considered valid in various formats + --not-before string earliest date and time the certificate is considered valid in various formats (default is now) -o, --organization strings certificate organization (default [Authelia]) --organizational-unit strings certificate organizational unit -p, --postcode strings certificate postcode diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md index e00aaf877..9b89fba34 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_generate.md @@ -35,28 +35,31 @@ 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 - -n, --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 + -b, --bits int number of RSA bits for the certificate (default 2048) + --bundle enables generating the certificate bundle if the --path.ca flag is set + --ca create the certificate as a certificate authority certificate + -n, --common-name string certificate common name + --country strings certificate country + -d, --directory string directory where the generated keys, certificates, etc will be stored + --duration string duration of time the certificate is valid for (default "1y") + --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.certificate-bundle string name of the file to export the certificate bundle data to when the --bundle flag is set (default "public.bundle.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-after string latest date and time the certificate is considered valid in various formats + --not-before string earliest date and time the certificate is considered valid in various formats (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 ``` ### Options inherited from parent commands diff --git a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md index 544cbf553..8280c4ee3 100644 --- a/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md +++ b/docs/content/en/reference/cli/authelia/authelia_crypto_certificate_rsa_request.md @@ -39,12 +39,13 @@ authelia crypto certificate rsa request --help -n, --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) + --duration string duration of time the certificate is valid for (default "1y") --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) + --not-after string latest date and time the certificate is considered valid in various formats + --not-before string earliest date and time the certificate is considered valid in various formats (default is now) -o, --organization strings certificate organization (default [Authelia]) --organizational-unit strings certificate organizational unit -p, --postcode strings certificate postcode diff --git a/internal/commands/const.go b/internal/commands/const.go index bd60b22d4..ea56d2f5b 100644 --- a/internal/commands/const.go +++ b/internal/commands/const.go @@ -533,21 +533,19 @@ const ( storageMigrateDirectionDown = "down" ) -const ( - timeLayoutCertificateNotBefore = "Jan 2 15:04:05 2006" -) - const ( cmdFlagNameDirectory = "directory" cmdFlagNamePathCA = "path.ca" + cmdFlagNameBundle = "bundle" - cmdFlagNameFilePrivateKey = "file.private-key" - cmdFlagNameFilePublicKey = "file.public-key" - cmdFlagNameFileCertificate = "file.certificate" - cmdFlagNameFileCAPrivateKey = "file.ca-private-key" - cmdFlagNameFileCACertificate = "file.ca-certificate" - cmdFlagNameFileCSR = "file.csr" + cmdFlagNameFilePrivateKey = "file.private-key" + cmdFlagNameFilePublicKey = "file.public-key" + cmdFlagNameFileCertificate = "file.certificate" + cmdFlagNameFileCertificateBundle = "file.certificate-bundle" + cmdFlagNameFileCAPrivateKey = "file.ca-private-key" + cmdFlagNameFileCACertificate = "file.ca-certificate" + cmdFlagNameFileCSR = "file.csr" cmdFlagNameExtendedUsage = "extended-usage" cmdFlagNameSignature = "signature" @@ -564,6 +562,7 @@ const ( cmdFlagNamePostcode = "postcode" cmdFlagNameNotBefore = "not-before" + cmdFlagNameNotAfter = "not-after" cmdFlagNameDuration = "duration" cmdFlagNamePKCS8 = "pkcs8" @@ -749,4 +748,27 @@ Secrets: way: 'key', 'secret', 'password', 'token'. The available options and the specific secret mapping can be found here: https://www.authelia.com/configuration/methods/secrets/` + + helpTopicTimeLayouts = `Several commands take date time inputs which are parsed. These inputs are parsed with +specific layouts in mind and these layouts are handled in order. + +Format: + + The layouts use a format where specific sequence of characters are representative of a portion of each timestamp. + + See the go documentation for more information on how these layouts work, however the layouts are fairly self + explanatory and you can just use standard unix timestamps if desired. + +Layouts: + + Unix (µs): 1675899060000000 + Unix (ms): 1675899060000 + Unix (s): 1675899060 + Simple: Jan 2 15:04:05 2006 + Date Time: 2006-01-02 15:04:05 + RFC3339: 2006-01-02T15:04:05Z07:00 + RFC1123 with numeric timezone: Mon, 02 Jan 2006 15:04:05 -0700 + Ruby Date: Mon Jan 02 15:04:05 -0700 2006 + ANSIC: Mon Jan _2 15:04:05 2006 + Date: 2006-01-02` ) diff --git a/internal/commands/crypto.go b/internal/commands/crypto.go index 74c8d4099..fffec510c 100644 --- a/internal/commands/crypto.go +++ b/internal/commands/crypto.go @@ -313,7 +313,7 @@ func (ctx *CmdCtx) CryptoCertificateRequestRunE(cmd *cobra.Command, _ []string) 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 { + if _, privateKeyPath, csrPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { return err } @@ -329,15 +329,11 @@ func (ctx *CmdCtx) CryptoCertificateRequestRunE(cmd *cobra.Command, _ []string) 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 { + if err = utils.WriteCertificateBytesToPEM(csrPath, true, csr); err != nil { return err } @@ -406,21 +402,23 @@ func (ctx *CmdCtx) CryptoCertificateGenerateRunE(cmd *cobra.Command, _ []string, b.WriteString(fmt.Sprintf("\n\tSubject Alternative Names: %s\n\n", strings.Join(cryptoSANsToString(template.DNSNames, template.IPAddresses), ", "))) var ( - privateKeyPath, certificatePath string - certificate []byte + dir, privateKeyPath, certificatePath, certificateBundlePath string + + bundle bool + certificate []byte ) - if privateKeyPath, certificatePath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { + if dir, privateKeyPath, certificatePath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { + return err + } + + if bundle, certificateBundlePath, err = cryptoGetCertificateBundleFromCmd(cmd, dir, caCertificate); 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() + b.WriteString(fmt.Sprintf("\tCertificate: %s\n", certificatePath)) if certificate, err = x509.CreateCertificate(ctx.providers.Random, template, parent, publicKey, signatureKey); err != nil { return fmt.Errorf("failed to create certificate: %w", err) @@ -430,10 +428,24 @@ func (ctx *CmdCtx) CryptoCertificateGenerateRunE(cmd *cobra.Command, _ []string, return err } - if err = utils.WriteCertificateBytesToPEM(certificate, certificatePath, false); err != nil { + if err = utils.WriteCertificateBytesToPEM(certificatePath, false, certificate); err != nil { return err } + if bundle { + b.WriteString(fmt.Sprintf("\tCertificate (bundle): %s\n", certificateBundlePath)) + + if err = utils.WriteCertificateBytesToPEM(certificateBundlePath, false, certificate, caCertificate.Raw); err != nil { + return err + } + } + + b.WriteString("\n") + + fmt.Print(b.String()) + + b.Reset() + return nil } @@ -448,7 +460,7 @@ func (ctx *CmdCtx) CryptoPairGenerateRunE(cmd *cobra.Command, _ []string, privat return err } - if privateKeyPath, publicKeyPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { + if _, privateKeyPath, publicKeyPath, err = cryptoGetWritePathsFromCmd(cmd); err != nil { return err } diff --git a/internal/commands/crypto_helper.go b/internal/commands/crypto_helper.go index 17ee4060f..774c19548 100644 --- a/internal/commands/crypto_helper.go +++ b/internal/commands/crypto_helper.go @@ -32,8 +32,9 @@ func cmdFlagsCryptoCertificateCommon(cmd *cobra.Command) { 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().String(cmdFlagNameNotBefore, "", "earliest date and time the certificate is considered valid in various formats (default is now)") + cmd.Flags().String(cmdFlagNameNotAfter, "", "latest date and time the certificate is considered valid in various formats") + cmd.Flags().String(cmdFlagNameDuration, "1y", "duration of time the certificate is valid for") cmd.Flags().StringSlice(cmdFlagNameSANs, nil, "subject alternative names") } @@ -42,6 +43,8 @@ func cmdFlagsCryptoCertificateGenerate(cmd *cobra.Command) { 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().String(cmdFlagNameFileCertificateBundle, "public.bundle.crt", fmt.Sprintf("name of the file to export the certificate bundle data to when the --%s flag is set", cmdFlagNameBundle)) + cmd.Flags().Bool(cmdFlagNameBundle, false, fmt.Sprintf("enables generating the certificate bundle if the --%s flag is set", cmdFlagNamePathCA)) cmd.Flags().StringSlice(cmdFlagNameExtendedUsage, nil, "specify the extended usage types of the certificate") @@ -91,17 +94,15 @@ func cryptoSANsToString(dnsSANs []string, ipSANs []net.IP) (sans []string) { return sans } -func cryptoGetWritePathsFromCmd(cmd *cobra.Command) (privateKey, publicKey string, err error) { - var dir string - +func cryptoGetWritePathsFromCmd(cmd *cobra.Command) (dir, privateKey, publicKey string, err error) { if dir, err = cmd.Flags().GetString(cmdFlagNameDirectory); err != nil { - return "", "", err + return "", "", "", err } ca, _ := cmd.Flags().GetBool(cmdFlagNameCA) csr := cmd.Use == cmdUseRequest - var private, public string + var pathPrivate, pathPublic string var flagPrivate, flagPublic string @@ -118,15 +119,15 @@ func cryptoGetWritePathsFromCmd(cmd *cobra.Command) (privateKey, publicKey strin flagPrivate, flagPublic = cmdFlagNameFilePrivateKey, cmdFlagNameFileCertificate } - if private, err = cmd.Flags().GetString(flagPrivate); err != nil { - return "", "", err + if pathPrivate, err = cmd.Flags().GetString(flagPrivate); err != nil { + return "", "", "", err } - if public, err = cmd.Flags().GetString(flagPublic); err != nil { - return "", "", err + if pathPublic, err = cmd.Flags().GetString(flagPublic); err != nil { + return "", "", "", err } - return filepath.Join(dir, private), filepath.Join(dir, public), nil + return dir, filepath.Join(dir, pathPrivate), filepath.Join(dir, pathPublic), nil } func (ctx *CmdCtx) cryptoGenPrivateKeyFromCmd(cmd *cobra.Command) (privateKey any, err error) { @@ -169,6 +170,28 @@ func (ctx *CmdCtx) cryptoGenPrivateKeyFromCmd(cmd *cobra.Command) (privateKey an return privateKey, nil } +func cryptoGetCertificateBundleFromCmd(cmd *cobra.Command, dir string, caCertificate *x509.Certificate) (bundle bool, bundlePath string, err error) { + if bundle, err = cmd.Flags().GetBool(cmdFlagNameBundle); err != nil { + return false, "", err + } + + if !bundle { + return bundle, bundlePath, err + } + + if caCertificate == nil { + return false, "", fmt.Errorf("the --%s flag can't be used with self-signed certificates, you can specify the authority path using the --%s flag", cmdFlagNameBundle, cmdFlagNamePathCA) + } + + if bundlePath, err = cmd.Flags().GetString(cmdFlagNameFileCertificateBundle); err != nil { + return false, "", err + } + + bundlePath = filepath.Join(dir, bundlePath) + + return bundle, bundlePath, err +} + func cryptoGetCAFromCmd(cmd *cobra.Command) (privateKey any, cert *x509.Certificate, err error) { if !cmd.Flags().Changed(cmdFlagNamePathCA) { return nil, nil, nil @@ -337,10 +360,10 @@ func cryptoGetSubjectFromCmd(cmd *cobra.Command) (subject *pkix.Name, err error) func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate *x509.Certificate, err error) { var ( - ca bool - subject *pkix.Name - notBeforeStr string - duration time.Duration + ca bool + subject *pkix.Name + + notBefore, notAfter time.Time ) if ca, err = cmd.Flags().GetBool(cmdFlagNameCA); err != nil { @@ -351,30 +374,16 @@ func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate return nil, err } - if notBeforeStr, err = cmd.Flags().GetString(cmdFlagNameNotBefore); err != nil { - return nil, err - } - - if duration, err = cmd.Flags().GetDuration(cmdFlagNameDuration); err != nil { + if notBefore, notAfter, err = cryptoCertificateValidityFromCmd(cmd); 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 = ctx.providers.Random.IntErr(serialNumberLimit); err != nil { @@ -396,7 +405,7 @@ func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate Subject: *subject, NotBefore: notBefore, - NotAfter: notBefore.Add(duration), + NotAfter: notAfter, IsCA: ca, @@ -415,6 +424,57 @@ func (ctx *CmdCtx) cryptoGetCertificateFromCmd(cmd *cobra.Command) (certificate return certificate, nil } +func cryptoCertificateValidityFromCmd(cmd *cobra.Command) (notBefore, notAfter time.Time, err error) { + never := time.UnixMicro(0) + + switch cmd.Flags().Changed(cmdFlagNameNotBefore) { + case true: + var notBeforeStr string + + if notBeforeStr, err = cmd.Flags().GetString(cmdFlagNameNotBefore); err != nil { + return never, never, err + } + + if notBefore, err = utils.ParseTimeString(notBeforeStr); err != nil { + return never, never, fmt.Errorf("failed to parse not before: %w", err) + } + default: + notBefore = time.Now() + } + + switch useNotAfter := cmd.Flags().Changed(cmdFlagNameNotAfter); { + case useNotAfter && cmd.Flags().Changed(cmdFlagNameDuration): + return never, never, fmt.Errorf("failed to determine not after ") + case useNotAfter: + var notAfterStr string + + if notAfterStr, err = cmd.Flags().GetString(cmdFlagNameNotAfter); err != nil { + return never, never, err + } + + if notAfter, err = utils.ParseTimeString(notAfterStr); err != nil { + return never, never, fmt.Errorf("failed to parse not after: %w", err) + } + default: + var ( + durationStr string + duration time.Duration + ) + + if durationStr, err = cmd.Flags().GetString(cmdFlagNameDuration); err != nil { + return never, never, err + } + + if duration, err = utils.ParseDurationString(durationStr); err != nil { + return never, never, fmt.Errorf("failed to parse duration string: %w", err) + } + + notAfter = notBefore.Add(duration) + } + + return notBefore, notAfter, nil +} + func fmtCryptoHashUse(use string) string { switch use { case cmdUseHashArgon2: diff --git a/internal/commands/root.go b/internal/commands/root.go index 0ac6d8843..7b728eb5a 100644 --- a/internal/commands/root.go +++ b/internal/commands/root.go @@ -58,6 +58,7 @@ func NewRootCmd() (cmd *cobra.Command) { newHelpTopic("config", "Help for the config file/directory paths", helpTopicConfig), newHelpTopic("filters", "help topic for the config filters", helpTopicConfigFilters), + newHelpTopic("time-layouts", "help topic for the various time layouts", helpTopicTimeLayouts), ) return cmd diff --git a/internal/configuration/validator/configuration_test.go b/internal/configuration/validator/configuration_test.go index 0abf16372..77e35c3b7 100644 --- a/internal/configuration/validator/configuration_test.go +++ b/internal/configuration/validator/configuration_test.go @@ -160,7 +160,7 @@ func TestShouldRaiseErrorOnInvalidCertificatesDirectory(t *testing.T) { func TestShouldNotRaiseErrorOnValidCertificatesDirectory(t *testing.T) { validator := schema.NewStructValidator() config := newDefaultConfig() - config.CertificatesDirectory = "../../suites/common/ssl" + config.CertificatesDirectory = "../../suites/common/pki" ValidateConfiguration(&config, validator) diff --git a/internal/suites/ActiveDirectory/configuration.yml b/internal/suites/ActiveDirectory/configuration.yml index 31f09189f..3a11f94ff 100644 --- a/internal/suites/ActiveDirectory/configuration.yml +++ b/internal/suites/ActiveDirectory/configuration.yml @@ -10,8 +10,8 @@ default_redirection_url: https://home.example.com:8080/ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/ActiveDirectory/docker-compose.yml b/internal/suites/ActiveDirectory/docker-compose.yml index 84634997e..ac6f88202 100644 --- a/internal/suites/ActiveDirectory/docker-compose.yml +++ b/internal/suites/ActiveDirectory/docker-compose.yml @@ -4,5 +4,5 @@ services: authelia-backend: volumes: - './ActiveDirectory/configuration.yml:/config/configuration.yml:ro' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/BypassAll/configuration.yml b/internal/suites/BypassAll/configuration.yml index 8e5157fdc..e7e04abe2 100644 --- a/internal/suites/BypassAll/configuration.yml +++ b/internal/suites/BypassAll/configuration.yml @@ -6,8 +6,8 @@ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/BypassAll/docker-compose.yml b/internal/suites/BypassAll/docker-compose.yml index 943aa1b94..306d724ff 100644 --- a/internal/suites/BypassAll/docker-compose.yml +++ b/internal/suites/BypassAll/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './BypassAll/configuration.yml:/config/configuration.yml:ro' - './BypassAll/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/CLI/configuration.yml b/internal/suites/CLI/configuration.yml index a01f2a06b..18ec44c1d 100644 --- a/internal/suites/CLI/configuration.yml +++ b/internal/suites/CLI/configuration.yml @@ -6,8 +6,8 @@ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/CLI/docker-compose.yml b/internal/suites/CLI/docker-compose.yml index 180ba191e..d38329137 100644 --- a/internal/suites/CLI/docker-compose.yml +++ b/internal/suites/CLI/docker-compose.yml @@ -6,7 +6,7 @@ services: - './CLI/configuration.yml:/config/configuration.yml:ro' - './CLI/storage.yml:/config/configuration.storage.yml:ro' - './CLI/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' - '/tmp:/tmp' user: ${USER_ID}:${GROUP_ID} ... diff --git a/internal/suites/Caddy/configuration.yml b/internal/suites/Caddy/configuration.yml index 38031dcdc..14f9fdff0 100644 --- a/internal/suites/Caddy/configuration.yml +++ b/internal/suites/Caddy/configuration.yml @@ -9,8 +9,8 @@ server: port: 9091 asset_path: /config/assets/ tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem endpoints: authz: caddy: diff --git a/internal/suites/Caddy/docker-compose.yml b/internal/suites/Caddy/docker-compose.yml index cc2b579b4..2b5a105a5 100644 --- a/internal/suites/Caddy/docker-compose.yml +++ b/internal/suites/Caddy/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './Caddy/configuration.yml:/config/configuration.yml:ro' - './Caddy/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/Docker/configuration.yml b/internal/suites/Docker/configuration.yml index 095e9fdb1..706ff86e2 100644 --- a/internal/suites/Docker/configuration.yml +++ b/internal/suites/Docker/configuration.yml @@ -9,8 +9,8 @@ default_redirection_url: https://home.example.com:8080/ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/Docker/docker-compose.yml b/internal/suites/Docker/docker-compose.yml index 0e1c25b29..9c6aae12d 100644 --- a/internal/suites/Docker/docker-compose.yml +++ b/internal/suites/Docker/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './Docker/configuration.yml:/config/configuration.yml:ro' - './Docker/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/DuoPush/configuration.yml b/internal/suites/DuoPush/configuration.yml index 79c40ec3a..0d8c3abf2 100644 --- a/internal/suites/DuoPush/configuration.yml +++ b/internal/suites/DuoPush/configuration.yml @@ -9,8 +9,8 @@ default_redirection_url: https://home.example.com:8080/ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: trace diff --git a/internal/suites/DuoPush/docker-compose.yml b/internal/suites/DuoPush/docker-compose.yml index f5afb5812..f5799b427 100644 --- a/internal/suites/DuoPush/docker-compose.yml +++ b/internal/suites/DuoPush/docker-compose.yml @@ -5,7 +5,7 @@ services: volumes: - './DuoPush/configuration.yml:/config/configuration.yml:ro' - './DuoPush/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' - '/tmp:/tmp' user: ${USER_ID}:${GROUP_ID} ... diff --git a/internal/suites/Envoy/configuration.yml b/internal/suites/Envoy/configuration.yml index 6a5ff2021..eaf11e4fd 100644 --- a/internal/suites/Envoy/configuration.yml +++ b/internal/suites/Envoy/configuration.yml @@ -9,8 +9,8 @@ server: port: 9091 asset_path: /config/assets/ tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem endpoints: authz: ext-authz: diff --git a/internal/suites/Envoy/docker-compose.yml b/internal/suites/Envoy/docker-compose.yml index 194d32ab4..1063b0799 100644 --- a/internal/suites/Envoy/docker-compose.yml +++ b/internal/suites/Envoy/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './Envoy/configuration.yml:/config/configuration.yml:ro' - './Envoy/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/HAProxy/configuration.yml b/internal/suites/HAProxy/configuration.yml index ddbe9e58e..55811316f 100644 --- a/internal/suites/HAProxy/configuration.yml +++ b/internal/suites/HAProxy/configuration.yml @@ -8,8 +8,8 @@ jwt_secret: unsecure_secret server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/HAProxy/docker-compose.yml b/internal/suites/HAProxy/docker-compose.yml index c6f7a5dc1..ca67c5135 100644 --- a/internal/suites/HAProxy/docker-compose.yml +++ b/internal/suites/HAProxy/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './HAProxy/configuration.yml:/config/configuration.yml:ro' - './HAProxy/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/HighAvailability/configuration.yml b/internal/suites/HighAvailability/configuration.yml index 530b9bdf3..02822df2b 100644 --- a/internal/suites/HighAvailability/configuration.yml +++ b/internal/suites/HighAvailability/configuration.yml @@ -8,8 +8,8 @@ jwt_secret: unsecure_secret server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/HighAvailability/docker-compose.yml b/internal/suites/HighAvailability/docker-compose.yml index 15bc66e04..87914c061 100644 --- a/internal/suites/HighAvailability/docker-compose.yml +++ b/internal/suites/HighAvailability/docker-compose.yml @@ -4,5 +4,5 @@ services: authelia-backend: volumes: - './HighAvailability/configuration.yml:/config/configuration.yml:ro' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/LDAP/configuration.yml b/internal/suites/LDAP/configuration.yml index 120e89224..2d28b704a 100644 --- a/internal/suites/LDAP/configuration.yml +++ b/internal/suites/LDAP/configuration.yml @@ -10,8 +10,8 @@ default_redirection_url: https://home.example.com:8080/ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/LDAP/docker-compose.yml b/internal/suites/LDAP/docker-compose.yml index e00299c59..5dc2a34cb 100644 --- a/internal/suites/LDAP/docker-compose.yml +++ b/internal/suites/LDAP/docker-compose.yml @@ -4,5 +4,5 @@ services: authelia-backend: volumes: - './LDAP/configuration.yml:/config/configuration.yml:ro' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/MariaDB/configuration.yml b/internal/suites/MariaDB/configuration.yml index e575b1408..b4fae1e60 100644 --- a/internal/suites/MariaDB/configuration.yml +++ b/internal/suites/MariaDB/configuration.yml @@ -9,8 +9,8 @@ default_redirection_url: https://home.example.com:8080/ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/MariaDB/docker-compose.yml b/internal/suites/MariaDB/docker-compose.yml index dbe20d3b2..60c852c16 100644 --- a/internal/suites/MariaDB/docker-compose.yml +++ b/internal/suites/MariaDB/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './MariaDB/configuration.yml:/config/configuration.yml:ro' - './MariaDB/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/MultiCookieDomain/configuration.yml b/internal/suites/MultiCookieDomain/configuration.yml index 30e194678..f0ce576f8 100644 --- a/internal/suites/MultiCookieDomain/configuration.yml +++ b/internal/suites/MultiCookieDomain/configuration.yml @@ -9,8 +9,8 @@ theme: auto server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem telemetry: metrics: diff --git a/internal/suites/MultiCookieDomain/docker-compose.yml b/internal/suites/MultiCookieDomain/docker-compose.yml index 1a2f0122b..117eefee3 100644 --- a/internal/suites/MultiCookieDomain/docker-compose.yml +++ b/internal/suites/MultiCookieDomain/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './MultiCookieDomain/configuration.yml:/config/configuration.yml:ro' - './MultiCookieDomain/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/MySQL/configuration.yml b/internal/suites/MySQL/configuration.yml index 7dd065be9..c41a4d3ac 100644 --- a/internal/suites/MySQL/configuration.yml +++ b/internal/suites/MySQL/configuration.yml @@ -6,8 +6,8 @@ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/MySQL/docker-compose.yml b/internal/suites/MySQL/docker-compose.yml index a360680e1..bc6dabe1c 100644 --- a/internal/suites/MySQL/docker-compose.yml +++ b/internal/suites/MySQL/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './MySQL/configuration.yml:/config/configuration.yml:ro' - './MySQL/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/NetworkACL/configuration.yml b/internal/suites/NetworkACL/configuration.yml index c07cfe3ee..d90e84815 100644 --- a/internal/suites/NetworkACL/configuration.yml +++ b/internal/suites/NetworkACL/configuration.yml @@ -6,8 +6,8 @@ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/NetworkACL/docker-compose.yml b/internal/suites/NetworkACL/docker-compose.yml index ae77fe1fc..c19338554 100644 --- a/internal/suites/NetworkACL/docker-compose.yml +++ b/internal/suites/NetworkACL/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './NetworkACL/configuration.yml:/config/configuration.yml:ro' - './NetworkACL/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/OIDC/configuration.yml b/internal/suites/OIDC/configuration.yml index 0b1d17f2f..f8fb2a8c7 100644 --- a/internal/suites/OIDC/configuration.yml +++ b/internal/suites/OIDC/configuration.yml @@ -2,8 +2,8 @@ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/OIDC/docker-compose.yml b/internal/suites/OIDC/docker-compose.yml index 2da124b77..90137cac1 100644 --- a/internal/suites/OIDC/docker-compose.yml +++ b/internal/suites/OIDC/docker-compose.yml @@ -6,5 +6,5 @@ services: - './OIDC/configuration.yml:/config/configuration.yml:ro' - './OIDC/users.yml:/config/users.yml' - './OIDC/keypair/key.pem:/config/issuer.pem:ro' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/OIDCTraefik/configuration.yml b/internal/suites/OIDCTraefik/configuration.yml index 2e089fda9..e9c8dd532 100644 --- a/internal/suites/OIDCTraefik/configuration.yml +++ b/internal/suites/OIDCTraefik/configuration.yml @@ -2,8 +2,8 @@ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/OIDCTraefik/docker-compose.yml b/internal/suites/OIDCTraefik/docker-compose.yml index a5f4dd820..429492cff 100644 --- a/internal/suites/OIDCTraefik/docker-compose.yml +++ b/internal/suites/OIDCTraefik/docker-compose.yml @@ -6,5 +6,5 @@ services: - './OIDCTraefik/configuration.yml:/config/configuration.yml:ro' - './OIDCTraefik/users.yml:/config/users.yml' - './OIDCTraefik/keypair/key.pem:/config/issuer.pem:ro' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/OneFactorOnly/configuration.yml b/internal/suites/OneFactorOnly/configuration.yml index bc3ac4485..e53e40bff 100644 --- a/internal/suites/OneFactorOnly/configuration.yml +++ b/internal/suites/OneFactorOnly/configuration.yml @@ -9,8 +9,8 @@ default_redirection_url: https://home.example.com:8080/ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/OneFactorOnly/docker-compose.yml b/internal/suites/OneFactorOnly/docker-compose.yml index fc9276507..673704fed 100644 --- a/internal/suites/OneFactorOnly/docker-compose.yml +++ b/internal/suites/OneFactorOnly/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './OneFactorOnly/configuration.yml:/config/configuration.yml:ro' - './OneFactorOnly/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/PathPrefix/configuration.yml b/internal/suites/PathPrefix/configuration.yml index decb58436..eb2cfe57c 100644 --- a/internal/suites/PathPrefix/configuration.yml +++ b/internal/suites/PathPrefix/configuration.yml @@ -9,8 +9,8 @@ server: port: 9091 path: auth tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/PathPrefix/docker-compose.yml b/internal/suites/PathPrefix/docker-compose.yml index 428f056ce..92985d4cc 100644 --- a/internal/suites/PathPrefix/docker-compose.yml +++ b/internal/suites/PathPrefix/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './PathPrefix/configuration.yml:/config/configuration.yml:ro' - './PathPrefix/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/Postgres/configuration.yml b/internal/suites/Postgres/configuration.yml index ebeba850a..66af743af 100644 --- a/internal/suites/Postgres/configuration.yml +++ b/internal/suites/Postgres/configuration.yml @@ -9,8 +9,8 @@ default_redirection_url: https://home.example.com:8080/ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/Postgres/docker-compose.yml b/internal/suites/Postgres/docker-compose.yml index 187ba6661..46e4a07f2 100644 --- a/internal/suites/Postgres/docker-compose.yml +++ b/internal/suites/Postgres/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './Postgres/configuration.yml:/config/configuration.yml:ro' - './Postgres/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/ShortTimeouts/configuration.yml b/internal/suites/ShortTimeouts/configuration.yml index 82bcb9149..8e0e594c1 100644 --- a/internal/suites/ShortTimeouts/configuration.yml +++ b/internal/suites/ShortTimeouts/configuration.yml @@ -9,8 +9,8 @@ default_redirection_url: https://home.example.com:8080/ server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/ShortTimeouts/docker-compose.yml b/internal/suites/ShortTimeouts/docker-compose.yml index 6568c9d45..f5d2b5cf5 100644 --- a/internal/suites/ShortTimeouts/docker-compose.yml +++ b/internal/suites/ShortTimeouts/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './ShortTimeouts/configuration.yml:/config/configuration.yml:ro' - './ShortTimeouts/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/Standalone/configuration.yml b/internal/suites/Standalone/configuration.yml index 0deb53017..9b4186a11 100644 --- a/internal/suites/Standalone/configuration.yml +++ b/internal/suites/Standalone/configuration.yml @@ -8,8 +8,8 @@ theme: auto server: port: 9091 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem telemetry: metrics: diff --git a/internal/suites/Standalone/docker-compose.yml b/internal/suites/Standalone/docker-compose.yml index 1aaabf6b4..6dd37796f 100644 --- a/internal/suites/Standalone/docker-compose.yml +++ b/internal/suites/Standalone/docker-compose.yml @@ -8,7 +8,7 @@ services: volumes: - './Standalone/configuration.yml:/config/configuration.yml:ro' - './Standalone/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' - '/tmp:/tmp' user: ${USER_ID}:${GROUP_ID} ... diff --git a/internal/suites/Traefik/configuration.yml b/internal/suites/Traefik/configuration.yml index babc67281..cdf2326a8 100644 --- a/internal/suites/Traefik/configuration.yml +++ b/internal/suites/Traefik/configuration.yml @@ -9,8 +9,8 @@ server: port: 9091 asset_path: /config/assets/ tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/Traefik/docker-compose.yml b/internal/suites/Traefik/docker-compose.yml index a80813d91..2e8524c8c 100644 --- a/internal/suites/Traefik/docker-compose.yml +++ b/internal/suites/Traefik/docker-compose.yml @@ -5,5 +5,5 @@ services: volumes: - './Traefik/configuration.yml:/config/configuration.yml:ro' - './Traefik/users.yml:/config/users.yml' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/Traefik2/configuration.yml b/internal/suites/Traefik2/configuration.yml index 93da678a0..7289f1086 100644 --- a/internal/suites/Traefik2/configuration.yml +++ b/internal/suites/Traefik2/configuration.yml @@ -9,8 +9,8 @@ server: port: 9091 asset_path: /config/assets/ tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem endpoints: authz: forward-auth: diff --git a/internal/suites/Traefik2/docker-compose.yml b/internal/suites/Traefik2/docker-compose.yml index 4cdf56953..0a970db9f 100644 --- a/internal/suites/Traefik2/docker-compose.yml +++ b/internal/suites/Traefik2/docker-compose.yml @@ -7,5 +7,5 @@ services: - './Traefik2/users.yml:/config/users.yml' - './Traefik2/favicon.ico:/config/assets/favicon.ico' - './Traefik2/logo.png:/config/assets/logo.png' - - './common/ssl:/config/ssl:ro' + - './common/pki:/config/ssl:ro' ... diff --git a/internal/suites/common/pki/ca.public.crt b/internal/suites/common/pki/ca.public.crt new file mode 100644 index 000000000..98244a4ce --- /dev/null +++ b/internal/suites/common/pki/ca.public.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDhTCCAm2gAwIBAgIRAPl83YWFsuwIwxBRmdJyLLQwDQYJKoZIhvcNAQELBQAw +WzERMA8GA1UEChMIQXV0aGVsaWExFDASBgNVBAsTC0RldmVsb3BtZW50MTAwLgYD +VQQDEydBdXRoZWxpYSBEZXZlbG9wbWVudCBTdGFuZGFsb25lIFJvb3QgQ0EwIBcN +MDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMFsxETAPBgNVBAoTCEF1dGhl +bGlhMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEwMC4GA1UEAxMnQXV0aGVsaWEgRGV2 +ZWxvcG1lbnQgU3RhbmRhbG9uZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA2RtD74ISXHruAIIkIRTLGf5VK0b7iN5+CPW8qWjg74PCnid1 +3DOqVCZ3HSXMP0iaH5rd+WAYojQo5Z1uZ75tXgzYjt6tyXG5H1nN1fkmjkHyNORP +abOZtngVaixvlT/hsONXszFdqogXhhI4DtEo0lvxJcnOHER4QVylM4YgDMF85jXi +VD893Y6Luik9B6FXLVK9iAJ5MfvD/r8kEPLsDTl2u/Ye0q4igVDJq9tOtb2enhlz +HtipYhzzNwEzQwy3tjzP9xpQG6XE6/JW20gQaBvoRBN64DMgRlh1/8ZVyYE8v/B1 +vRVpSgmyCdDJeaRYZ6J+hO3LXBXU20CVZsM5VQIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUlrBVtyTWJQWRimLeZXr2 +mrOzy2gwDQYJKoZIhvcNAQELBQADggEBAKXjAw5v8VTM6EDiUvR8XdiikYkycAG/ +hcEt+QLkkBb72+tUNYbr57YJeJuqQcaPTBUQrIXsID8JV5dQJFfyIG2s3G0iuN70 +W4fSRPqsSBIcyOK+2APLjkYV8qwLdh03Lyll4SZo7PCK8ItemsIK1NWhd74N49fm ++a8eyY5bgfA0FMkjY/ts4gAnYExGRoLOQRu/CgOvBlj2KQUrSNptze1rNlP32b63 +eUv1wf/ajK2TxI1pQgkeu2lM3Tyu7q7J4UVn0UY0wtZvHtw2+UBGKZB3ok6ejBy2 +HMjgLGuayGjhyUN8zRkuSvBynuI2wGhIlHklEbaQW5oFKbniXRqdzc4= +-----END CERTIFICATE----- diff --git a/internal/suites/common/pki/gen.sh b/internal/suites/common/pki/gen.sh new file mode 100755 index 000000000..3be773738 --- /dev/null +++ b/internal/suites/common/pki/gen.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +go run ./cmd/authelia crypto certificate rsa generate --directory ./internal/suites/common/pki -n 'Authelia Development Standalone Root CA' --not-before 'Jan 1 00:00:00 2000' --not-after 'Jan 1 00:00:00 2100' -o 'Authelia' --organizational-unit 'Development' --ca +go run ./cmd/authelia crypto certificate rsa generate --directory ./internal/suites/common/pki --path.ca ./internal/suites/common/pki/ -n '*.example.com' --sans '*.example.com,example.com' --not-before 'Jan 1 00:00:00 2000' --not-after 'Jan 1 00:00:00 2100' -o 'Authelia' --organizational-unit 'Development' --bundle +go run ./cmd/authelia crypto certificate rsa generate --directory ./internal/suites/common/pki --path.ca ./internal/suites/common/pki/ --file.certificate public.backend.crt --file.certificate-bundle public.backend.bundle.crt --file.private-key private.backend.pem -n 'login.example.com' --sans 'login.example.com,authelia' --not-before 'Jan 1 00:00:00 2000' --not-after 'Jan 1 00:00:00 2100' -o 'Authelia' --organizational-unit 'Development' --bundle diff --git a/internal/suites/common/pki/private.backend.pem b/internal/suites/common/pki/private.backend.pem new file mode 100644 index 000000000..5ea04fc99 --- /dev/null +++ b/internal/suites/common/pki/private.backend.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA9sWvS9YsIUlm4w3ikVUjsCg1hbwyb/BSEGpRsVG8Oox0t62R +MEIG70lPfMg2IeJZDDdFreLru3WXjHgo4ovp6bcyDtSkE7sRMhw8sATmmHNI0/Mz +ImDS4r87LP5JqYY4iS6c24j41HaKBMhTEk2oQ0fXGOP4/q6Pzu4JClaF0ZGrQbdp +dL+5aPL/0UX2Y3Ybq08vRQ8X5LUrKdEnrBeChrbfybjhOyNtllt49CmUsRYQVro5 +A2VTfroWSU7UfVUBPlI9UrATNvBmX+5fbctM6Go30dWsRXnlk4IcZHoUaA+6satK +HoWqzY9T4cQuNDSCTMe3TVT8VgYjrGWe9tQYRQIDAQABAoIBAGzgTXZFOVU6YHWf +I66BhOxs4ShvH0W6H0r0zbRRXp3qaHi90IgdKZgbnUFtyExs5GL6Y/jTXLRproKg +ZVGG755ZYHGgqf+2kmCsiq4Si3cJrkEtVQs+8uxt+Prh+rgb6wfDlBtcNITxA/YW +OGij8LA2mxV1R99+Px7KcRypjgMmx0Dp3NDoYE9Hj2VRVRLTo06WpZ7Mo9zfXtx6 +MHeJwmSerWzERvUHmrX4hG8Do3cygYnd8EartBjCIa/qambXlz7uG1ip3/v05VJi +w28VUVEERASy2W/OJjwe8QSmUQ/1HzKz+Vv/WCEvVINQr/o4TwJeZrASQ6bj1JCa +CVR8mCUCgYEA+lZhEYnmuypNhJsBwQJJIvqIIF4zrRqojax5kWAiRDJY2AYAxozG +K/WP3NWrR+k+Q+wdzad9QBddLru1ykhBSPLGbvU2cupyiSDMg6R5vL4xcdWSD1Ej +VKSUxSgP0ue7GeMsTgr8vT59UG7R6Mc6+H5ZLt6q3DsOwqs8He6NSa8CgYEA/Fqp +HhaOSz85GWPtMUdsXJC14WiKmKDaCYxiQ9QUP8l7M8xPSiarhh9xc2EZDjSOR/SU +jmDSCFUvQHE0H9xdWp69W15bxnD6Z4uSrAFWThsRdp9kRckcKLUDuumoeOL3WI3x +gS49YS5uEP08oSPpsD4P98Llw+l/UimFI4RDHksCgYEAvpC86d4BL59fTT+2URgN +VrxCnek4C2FMyDRwgpMc4q805JWFR5/oR5RyRFi/P0m15Xy7n08N0Jk4jRfFpkvk +rsRo/BRcs5P3Rp4aMWgmZ+CcwRwkSNaqP4fd3EvH5/QRgP5nPq2sgd8tA+qojjwD +jyCXgU9t36JxdQ1nAR4Une8CgYEAx+7APGFcfUtq3q3n13oh5TiVkS+1VvVhqdz6 +YYjePidQIBrH2xTGIm45AVO1eSa0b1fcdu1Immd7F1BZHsEFiW1o0sHwbklGatEO +9I3epeUWMehYll2enLXFbcn/uz7+/r7+zv0mjh8t/vHTnkuIsySInCBiz5PoVt0k +aZ45Wv8CgYAGj1ojQXs3SWQ+YY+rWrcMJ8atz9M4e7s8gEFiSp68ooi1kiVEKA2S +h4O79oksTAS1mgHiG237X6mJMkENpbPh8FR0hTcXbSyd7Ruki6h0LQnyXPGoV6KF +sojGWnJVDAtDMIT/z+tY4aeJbcicIgwS9oZ+dXQ/eQZiGKGOVexzwQ== +-----END RSA PRIVATE KEY----- diff --git a/internal/suites/common/pki/private.pem b/internal/suites/common/pki/private.pem new file mode 100644 index 000000000..91bb09086 --- /dev/null +++ b/internal/suites/common/pki/private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA0XIlKyTMa1e+vaOnT8kTJza2lacZMoykLr4NmxcQnKRe09Xd +U6IqhsaaielJe2JdkzHKQID+F/jxlNWqbHU65KSPfMtJ59De4boZ0DjuzKoiCV77 +HBj4mZg2PWEyerZU+JPLMhtIpnlbrzTeEjBpma51nXi/ELREYZsstEWNZ2RVaxwL +MKlAeDNVJotiLPMYA1rRJNa5Z3U9GPgy6l/F66NUd8klRuqJGeLDmlBu7NoRKhCX +DDk9VlATS5dBCde8rh/mGbkmNGrAa5sJFGaCZ9bDvroV31r2GdevbBY9+kXc3Vmi +eAlUarz5/B6jlV+CpwzKaGqcRSjEVMHobeb50wIDAQABAoIBAQCZSq/FefNbhScH +aSXlkUdBZhwQP/KDOshXpaYTorf3zZ3R8S9CLOhvKCCnW2T6ty3Bs6lRuJdAOGWo +BxHqu4pVGdQjBC6dShQ2pZyK94Bfrw2mSiwDjos072CTX/YwNg7OuGz5yVpM7Xmb +LFh0e5Zucm+Gx38f3LBHt+jqMBWkW0ir79kCn+pWzb5exMbr5khE1DbTLT4fu2he +1BYtq3aF3H1hxLsFGCSNBz0ocgTeRomrFH/gvn+WHBuS1GGR9gRFUqAC9ty4ej+l +yZ6n3Dt2bzNk7t/59s1FJoT4cYUQuxUnUxN+MHFIp9anDEUqO7yfw7GVFaLmj5lV +rnZNfV8RAoGBAPxc0cPO7eGvtFF26rJSacBqDvxLef4dEcRsyLHGbcLV2EhChSRy +ukHG8JZpDaG5dzFP0MRMNQ/TgrBOLypEH9QQgRDS+vx3xDQv/dtcsrQi1JTQ7K97 +Nye3dZnH5YwW7SuZPcrBqc7NnGLWwAP9gJH9BULQEYPztkLimHMfrVMHAoGBANR2 ++DMb3/TTtCI+XjWhUPMH7pgKjzP9UrkUYosRmSikAttJZYmWhy3sfDbzSm/y+G5r +aECJ3SwhdzRkUStUPi2z7L9zIdysKhXrZqxx3eiT9lX5en/CY57tTHU5U/Gco7ue +LToBLa/QVhUpQsM14GtTCx6kVt/1Ca9vMhKJhbPVAoGBAJKgY4h/bJuaeQx0KX0e +gS848CgKuoC45x/XjOwtvIxdr2Kcs7svpaSeMB9UPoVeuzA9jbDgDlx5qg9B/gly +t4OBa1wZGZcjBy7DS53uyC39psIoebyjvLIo1/1XtbmlgHu6d7qct0rfECQlXj9z +RQaNmkbtmZ+vNJC8E5OgLhZ1AoGAEMHlZ5qOOnAsJ/tFUPONP+3jOqiyjMYxLRnX +f+J+cv8knokWchimRs/9KBReTaAbShI8ocJ96EonbcFvyXwWf2JOjPcWt6H4m8v6 +SCWe/AYXisZnjAYX92P+AMzpuwfAvj6GkKmhIdnLwFWFx4HLVouxN9R8aaOZBPY/ +O8kO+5UCgYEAhyz0n7kvOqafNSgjTbXGoxTXWhgVEJYtEAd5xj5XzMeprVEY68+l +goJc6ww+Etq5/ghbtONW5d9Zy+BNcVMtZkNJr7j6XCzm0VEa6ZiKZK2HpZrkvbif +YQ3YOkW6583FXQCF67MuR2lbcDcLX9qgLT6MbAwiSL4Ow8qnLpz4CHA= +-----END RSA PRIVATE KEY----- diff --git a/internal/suites/common/pki/public.backend.bundle.crt b/internal/suites/common/pki/public.backend.bundle.crt new file mode 100644 index 000000000..fb651b78e --- /dev/null +++ b/internal/suites/common/pki/public.backend.bundle.crt @@ -0,0 +1,43 @@ +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMThBFxQ+GQhzdihMNsQxgEwDQYJKoZIhvcNAQELBQAw +WzERMA8GA1UEChMIQXV0aGVsaWExFDASBgNVBAsTC0RldmVsb3BtZW50MTAwLgYD +VQQDEydBdXRoZWxpYSBEZXZlbG9wbWVudCBTdGFuZGFsb25lIFJvb3QgQ0EwIBcN +MDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMEUxETAPBgNVBAoTCEF1dGhl +bGlhMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEaMBgGA1UEAxMRbG9naW4uZXhhbXBs +ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD2xa9L1iwhSWbj +DeKRVSOwKDWFvDJv8FIQalGxUbw6jHS3rZEwQgbvSU98yDYh4lkMN0Wt4uu7dZeM +eCjii+nptzIO1KQTuxEyHDywBOaYc0jT8zMiYNLivzss/kmphjiJLpzbiPjUdooE +yFMSTahDR9cY4/j+ro/O7gkKVoXRkatBt2l0v7lo8v/RRfZjdhurTy9FDxfktSsp +0SesF4KGtt/JuOE7I22WW3j0KZSxFhBWujkDZVN+uhZJTtR9VQE+Uj1SsBM28GZf +7l9ty0zoajfR1axFeeWTghxkehRoD7qxq0oeharNj1PhxC40NIJMx7dNVPxWBiOs +ZZ721BhFAgMBAAGjfjB8MA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF +BQcDATAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFJawVbck1iUFkYpi3mV69pqz +s8toMCYGA1UdEQQfMB2CEWxvZ2luLmV4YW1wbGUuY29tgghhdXRoZWxpYTANBgkq +hkiG9w0BAQsFAAOCAQEALqCLqIAM8wi0M12hMs4dARRtEEAZm/ff8B18SgBuES79 +qeas6pggPRmpfM3Ogjk+t8qG02yQeAF9zqAFXaI46kQxQohKcCrfW96pX91Tvuwc +x+3xsnHWj+FoI99uUGldDjVJoePXXB7wKB3/26o7dlcWry7y04cURvD3v/v/zABw +hPB5+t+5lB+kGSZg7ChnCDBLJx8/y9JTHKbZL3kHenvPHOn+T6aRQKNmAGpGwqV4 +Eq+lB/YKU9JADarOF5FCTux677JO1XdDcnooGZmbUrKbjzO/NnbREjBRZYfqJiV6 +uTz/I2MJ7IUiYh18xT3ZL2oUbnWly+TnR9oWnwSqLg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDhTCCAm2gAwIBAgIRAPl83YWFsuwIwxBRmdJyLLQwDQYJKoZIhvcNAQELBQAw +WzERMA8GA1UEChMIQXV0aGVsaWExFDASBgNVBAsTC0RldmVsb3BtZW50MTAwLgYD +VQQDEydBdXRoZWxpYSBEZXZlbG9wbWVudCBTdGFuZGFsb25lIFJvb3QgQ0EwIBcN +MDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMFsxETAPBgNVBAoTCEF1dGhl +bGlhMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEwMC4GA1UEAxMnQXV0aGVsaWEgRGV2 +ZWxvcG1lbnQgU3RhbmRhbG9uZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA2RtD74ISXHruAIIkIRTLGf5VK0b7iN5+CPW8qWjg74PCnid1 +3DOqVCZ3HSXMP0iaH5rd+WAYojQo5Z1uZ75tXgzYjt6tyXG5H1nN1fkmjkHyNORP +abOZtngVaixvlT/hsONXszFdqogXhhI4DtEo0lvxJcnOHER4QVylM4YgDMF85jXi +VD893Y6Luik9B6FXLVK9iAJ5MfvD/r8kEPLsDTl2u/Ye0q4igVDJq9tOtb2enhlz +HtipYhzzNwEzQwy3tjzP9xpQG6XE6/JW20gQaBvoRBN64DMgRlh1/8ZVyYE8v/B1 +vRVpSgmyCdDJeaRYZ6J+hO3LXBXU20CVZsM5VQIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUlrBVtyTWJQWRimLeZXr2 +mrOzy2gwDQYJKoZIhvcNAQELBQADggEBAKXjAw5v8VTM6EDiUvR8XdiikYkycAG/ +hcEt+QLkkBb72+tUNYbr57YJeJuqQcaPTBUQrIXsID8JV5dQJFfyIG2s3G0iuN70 +W4fSRPqsSBIcyOK+2APLjkYV8qwLdh03Lyll4SZo7PCK8ItemsIK1NWhd74N49fm ++a8eyY5bgfA0FMkjY/ts4gAnYExGRoLOQRu/CgOvBlj2KQUrSNptze1rNlP32b63 +eUv1wf/ajK2TxI1pQgkeu2lM3Tyu7q7J4UVn0UY0wtZvHtw2+UBGKZB3ok6ejBy2 +HMjgLGuayGjhyUN8zRkuSvBynuI2wGhIlHklEbaQW5oFKbniXRqdzc4= +-----END CERTIFICATE----- diff --git a/internal/suites/common/pki/public.backend.crt b/internal/suites/common/pki/public.backend.crt new file mode 100644 index 000000000..4ee5fe280 --- /dev/null +++ b/internal/suites/common/pki/public.backend.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMThBFxQ+GQhzdihMNsQxgEwDQYJKoZIhvcNAQELBQAw +WzERMA8GA1UEChMIQXV0aGVsaWExFDASBgNVBAsTC0RldmVsb3BtZW50MTAwLgYD +VQQDEydBdXRoZWxpYSBEZXZlbG9wbWVudCBTdGFuZGFsb25lIFJvb3QgQ0EwIBcN +MDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMEUxETAPBgNVBAoTCEF1dGhl +bGlhMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEaMBgGA1UEAxMRbG9naW4uZXhhbXBs +ZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD2xa9L1iwhSWbj +DeKRVSOwKDWFvDJv8FIQalGxUbw6jHS3rZEwQgbvSU98yDYh4lkMN0Wt4uu7dZeM +eCjii+nptzIO1KQTuxEyHDywBOaYc0jT8zMiYNLivzss/kmphjiJLpzbiPjUdooE +yFMSTahDR9cY4/j+ro/O7gkKVoXRkatBt2l0v7lo8v/RRfZjdhurTy9FDxfktSsp +0SesF4KGtt/JuOE7I22WW3j0KZSxFhBWujkDZVN+uhZJTtR9VQE+Uj1SsBM28GZf +7l9ty0zoajfR1axFeeWTghxkehRoD7qxq0oeharNj1PhxC40NIJMx7dNVPxWBiOs +ZZ721BhFAgMBAAGjfjB8MA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEF +BQcDATAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFJawVbck1iUFkYpi3mV69pqz +s8toMCYGA1UdEQQfMB2CEWxvZ2luLmV4YW1wbGUuY29tgghhdXRoZWxpYTANBgkq +hkiG9w0BAQsFAAOCAQEALqCLqIAM8wi0M12hMs4dARRtEEAZm/ff8B18SgBuES79 +qeas6pggPRmpfM3Ogjk+t8qG02yQeAF9zqAFXaI46kQxQohKcCrfW96pX91Tvuwc +x+3xsnHWj+FoI99uUGldDjVJoePXXB7wKB3/26o7dlcWry7y04cURvD3v/v/zABw +hPB5+t+5lB+kGSZg7ChnCDBLJx8/y9JTHKbZL3kHenvPHOn+T6aRQKNmAGpGwqV4 +Eq+lB/YKU9JADarOF5FCTux677JO1XdDcnooGZmbUrKbjzO/NnbREjBRZYfqJiV6 +uTz/I2MJ7IUiYh18xT3ZL2oUbnWly+TnR9oWnwSqLg== +-----END CERTIFICATE----- diff --git a/internal/suites/common/pki/public.bundle.crt b/internal/suites/common/pki/public.bundle.crt new file mode 100644 index 000000000..f1a59f447 --- /dev/null +++ b/internal/suites/common/pki/public.bundle.crt @@ -0,0 +1,43 @@ +-----BEGIN CERTIFICATE----- +MIIDpjCCAo6gAwIBAgIRAIVWl6KyC+LSDXvq138YbKkwDQYJKoZIhvcNAQELBQAw +WzERMA8GA1UEChMIQXV0aGVsaWExFDASBgNVBAsTC0RldmVsb3BtZW50MTAwLgYD +VQQDEydBdXRoZWxpYSBEZXZlbG9wbWVudCBTdGFuZGFsb25lIFJvb3QgQ0EwIBcN +MDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMEExETAPBgNVBAoTCEF1dGhl +bGlhMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEWMBQGA1UEAwwNKi5leGFtcGxlLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFyJSskzGtXvr2jp0/J +Eyc2tpWnGTKMpC6+DZsXEJykXtPV3VOiKobGmonpSXtiXZMxykCA/hf48ZTVqmx1 +OuSkj3zLSefQ3uG6GdA47syqIgle+xwY+JmYNj1hMnq2VPiTyzIbSKZ5W6803hIw +aZmudZ14vxC0RGGbLLRFjWdkVWscCzCpQHgzVSaLYizzGANa0STWuWd1PRj4Mupf +xeujVHfJJUbqiRniw5pQbuzaESoQlww5PVZQE0uXQQnXvK4f5hm5JjRqwGubCRRm +gmfWw766Fd9a9hnXr2wWPfpF3N1ZongJVGq8+fweo5VfgqcMymhqnEUoxFTB6G3m ++dMCAwEAAaN9MHswDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMB +MAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUlrBVtyTWJQWRimLeZXr2mrOzy2gw +JQYDVR0RBB4wHIINKi5leGFtcGxlLmNvbYILZXhhbXBsZS5jb20wDQYJKoZIhvcN +AQELBQADggEBAKF2dga/ZrglllTHZBqQdf//DkHpHfW/awxkOYDGKFNAosIQhn5d +cBC6fctnPugPw+97J6IaggP6ZDC8umlARWwsImxU2A6/uDoTZGdN3xrr2i0GOvho +bfz5FKJFte4MNYUii+IeuXJrzK7mZYXOS0iJwRmVs7euI2EZNQwE6ckMILRX2CmR +6CmvCrxKYhxZoo2P/tV+x5LZELHZ654rmUcug0mSJrtM6Hai94JazmYVfLWzLqvW +bTNav1MLJzqm32O9nFIBWOzq1Z77gdW/VnPwMeKBDwC/6p05p8b4kdsc+HtRq77M +5cObzCy4GcKIIgW5ovlTiLkAmWIkCUxIKMU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDhTCCAm2gAwIBAgIRAPl83YWFsuwIwxBRmdJyLLQwDQYJKoZIhvcNAQELBQAw +WzERMA8GA1UEChMIQXV0aGVsaWExFDASBgNVBAsTC0RldmVsb3BtZW50MTAwLgYD +VQQDEydBdXRoZWxpYSBEZXZlbG9wbWVudCBTdGFuZGFsb25lIFJvb3QgQ0EwIBcN +MDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMFsxETAPBgNVBAoTCEF1dGhl +bGlhMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEwMC4GA1UEAxMnQXV0aGVsaWEgRGV2 +ZWxvcG1lbnQgU3RhbmRhbG9uZSBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA2RtD74ISXHruAIIkIRTLGf5VK0b7iN5+CPW8qWjg74PCnid1 +3DOqVCZ3HSXMP0iaH5rd+WAYojQo5Z1uZ75tXgzYjt6tyXG5H1nN1fkmjkHyNORP +abOZtngVaixvlT/hsONXszFdqogXhhI4DtEo0lvxJcnOHER4QVylM4YgDMF85jXi +VD893Y6Luik9B6FXLVK9iAJ5MfvD/r8kEPLsDTl2u/Ye0q4igVDJq9tOtb2enhlz +HtipYhzzNwEzQwy3tjzP9xpQG6XE6/JW20gQaBvoRBN64DMgRlh1/8ZVyYE8v/B1 +vRVpSgmyCdDJeaRYZ6J+hO3LXBXU20CVZsM5VQIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUlrBVtyTWJQWRimLeZXr2 +mrOzy2gwDQYJKoZIhvcNAQELBQADggEBAKXjAw5v8VTM6EDiUvR8XdiikYkycAG/ +hcEt+QLkkBb72+tUNYbr57YJeJuqQcaPTBUQrIXsID8JV5dQJFfyIG2s3G0iuN70 +W4fSRPqsSBIcyOK+2APLjkYV8qwLdh03Lyll4SZo7PCK8ItemsIK1NWhd74N49fm ++a8eyY5bgfA0FMkjY/ts4gAnYExGRoLOQRu/CgOvBlj2KQUrSNptze1rNlP32b63 +eUv1wf/ajK2TxI1pQgkeu2lM3Tyu7q7J4UVn0UY0wtZvHtw2+UBGKZB3ok6ejBy2 +HMjgLGuayGjhyUN8zRkuSvBynuI2wGhIlHklEbaQW5oFKbniXRqdzc4= +-----END CERTIFICATE----- diff --git a/internal/suites/common/pki/public.crt b/internal/suites/common/pki/public.crt new file mode 100644 index 000000000..bae8cd61d --- /dev/null +++ b/internal/suites/common/pki/public.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDpjCCAo6gAwIBAgIRAIVWl6KyC+LSDXvq138YbKkwDQYJKoZIhvcNAQELBQAw +WzERMA8GA1UEChMIQXV0aGVsaWExFDASBgNVBAsTC0RldmVsb3BtZW50MTAwLgYD +VQQDEydBdXRoZWxpYSBEZXZlbG9wbWVudCBTdGFuZGFsb25lIFJvb3QgQ0EwIBcN +MDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMEExETAPBgNVBAoTCEF1dGhl +bGlhMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEWMBQGA1UEAwwNKi5leGFtcGxlLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFyJSskzGtXvr2jp0/J +Eyc2tpWnGTKMpC6+DZsXEJykXtPV3VOiKobGmonpSXtiXZMxykCA/hf48ZTVqmx1 +OuSkj3zLSefQ3uG6GdA47syqIgle+xwY+JmYNj1hMnq2VPiTyzIbSKZ5W6803hIw +aZmudZ14vxC0RGGbLLRFjWdkVWscCzCpQHgzVSaLYizzGANa0STWuWd1PRj4Mupf +xeujVHfJJUbqiRniw5pQbuzaESoQlww5PVZQE0uXQQnXvK4f5hm5JjRqwGubCRRm +gmfWw766Fd9a9hnXr2wWPfpF3N1ZongJVGq8+fweo5VfgqcMymhqnEUoxFTB6G3m ++dMCAwEAAaN9MHswDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMB +MAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUlrBVtyTWJQWRimLeZXr2mrOzy2gw +JQYDVR0RBB4wHIINKi5leGFtcGxlLmNvbYILZXhhbXBsZS5jb20wDQYJKoZIhvcN +AQELBQADggEBAKF2dga/ZrglllTHZBqQdf//DkHpHfW/awxkOYDGKFNAosIQhn5d +cBC6fctnPugPw+97J6IaggP6ZDC8umlARWwsImxU2A6/uDoTZGdN3xrr2i0GOvho +bfz5FKJFte4MNYUii+IeuXJrzK7mZYXOS0iJwRmVs7euI2EZNQwE6ckMILRX2CmR +6CmvCrxKYhxZoo2P/tV+x5LZELHZ654rmUcug0mSJrtM6Hai94JazmYVfLWzLqvW +bTNav1MLJzqm32O9nFIBWOzq1Z77gdW/VnPwMeKBDwC/6p05p8b4kdsc+HtRq77M +5cObzCy4GcKIIgW5ovlTiLkAmWIkCUxIKMU= +-----END CERTIFICATE----- diff --git a/internal/suites/common/ssl/cert.pem b/internal/suites/common/ssl/cert.pem deleted file mode 100644 index 9fabcb421..000000000 --- a/internal/suites/common/ssl/cert.pem +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIC/jCCAeagAwIBAgIRAKF0IRxC55eee6icERVf6fgwDQYJKoZIhvcNAQELBQAw -EjEQMA4GA1UEChMHQWNtZSBDbzAgFw0yMDAzMDExMjMzMzlaGA8yMTIwMDIwNjEy -MzMzOVowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAMi7/oSazFIxP3rHsSLjw5XPnpMKEaVwU1zLRzW6W80BDa/ER5to -I3POGLv8lAhtUwB6WvyilrCZfs/D5lkcCxswafU/2LNppFuODnW+PG9eobgOy6Nv -f+KbnZFPRV7PB2yK6DqMyb+tbTQ7F6rEf4i6n28DI0dNyNvUCk0ld3o93LZBvC/D -/+Ulf3Vtdfsd2TckXvdA8lH4VGQJ+FIxhboTlbW8VJlk1V7FZef7+m867kOnPSaj -zv5yygrIA0XPaMAZC/SZrXHMdhvcs43fgmmTel7JD4Sy/Z/pmFlrZr5Xa8jcWycJ -ILLuPnXhgKstgq5wtDkTMZ6rpgMrKcjMKcMCAwEAAaNNMEswDgYDVR0PAQH/BAQD -AgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwFgYDVR0RBA8w -DYILZXhhbXBsZS5jb20wDQYJKoZIhvcNAQELBQADggEBABdWkbipzPivAvvamMmQ -5iPPeStfdr5MBxJGT9nPbeXdtS/13FJnspLBMMYOw/2AZk7VFrNjxkXc4NHZSlGz -FcGMlSO40fyirdYaQTDtS230ucLB+LzfZx37y9dKpEKVmQ151kKJjJ4hAZ47LmAQ -aFoDLRo7PA2HmnJ60GrI9wVp96uy1sQ6PcToIyMcVEQ/tLEEow+ykSeiZb9+qBKV -K9GUcu2LorhBtUMmEWs0TJElaf6eKUoG6JXM2byulDg24w5b9gC26kAlHWc5WDU5 -pAXOjlN/OYHB0sDbYViWIL390376fYIfu2N5EDKY4QjEYsWEs4Wm9HVS9IgHP/Gi -Xbo= ------END CERTIFICATE----- diff --git a/internal/suites/common/ssl/key.pem b/internal/suites/common/ssl/key.pem deleted file mode 100644 index a190f8b44..000000000 --- a/internal/suites/common/ssl/key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDIu/6EmsxSMT96 -x7Ei48OVz56TChGlcFNcy0c1ulvNAQ2vxEebaCNzzhi7/JQIbVMAelr8opawmX7P -w+ZZHAsbMGn1P9izaaRbjg51vjxvXqG4Dsujb3/im52RT0Vezwdsiug6jMm/rW00 -OxeqxH+Iup9vAyNHTcjb1ApNJXd6Pdy2Qbwvw//lJX91bXX7Hdk3JF73QPJR+FRk -CfhSMYW6E5W1vFSZZNVexWXn+/pvOu5Dpz0mo87+csoKyANFz2jAGQv0ma1xzHYb -3LON34Jpk3peyQ+Esv2f6ZhZa2a+V2vI3FsnCSCy7j514YCrLYKucLQ5EzGeq6YD -KynIzCnDAgMBAAECggEAC13R0LJvRWwyewJZvm8FQTNreEoGq8aLgeKk2p792cLo -gn5ry5n+/+y4q9RmkX+XRpynEE0omUFn09306jDTVCvOpCuEWsxtmR2XJgWqqGfE -Yoa78zo6FJvZNUQ22mKAuh23frFAL1FjsKRz96B+1EA1DPUxhzUZXZFJMAsiE9LZ -PxqPmnqXbPZsOb1XG33TAdCp6CC3H8KHICC+i4IC8prjKHGH/Q1saoNw8jmgwv0S -DelQUbEtqfmE6BmyTGxdeu4uW2Nv/wcENwySAOPKi5gstlbSKTa4IpKGp7CdquWi -stUW6pnSiEeDrDAzwC8uWdncOvnkAy2lRJkz/F9YoQKBgQDrCCqYdvGshecBBnfQ -fowxak2YBfG2jhAKPMHzrvQn5FIb+11x/jeXPEfOB6FShIzZ97JpFIpH3tcONlj3 -OVzGCTD6WdRTcltzXVneJtNog7DliNFY4YmIPmQJ+y+EvJW1rSZTZAZI1Nbijg3n -fSd0PTzvgOGHSl1//RI1mFx7MwKBgQDapIPPSF0yf1UJ6Hhzam5NHGZ9fSqV5Qs0 -Gi7uM08iDV5K7xiPglBkbN2EuMlgVnHaa5g8X897uwRSYR6nL4PRvcJiNSvnhWhe -+K3x7iHewIPYVfcghoqzuPKsXH2Zm26usdXHxBBa3IBbKtGaHnAd9h65AOUYAmAx -C2BzN90XMQKBgE2MjEFyPZunMulrsOziVG+Zm7ClhXOuvCwkj/pPp8/hzhXdgp+y -ObV09lxMuDX59l+VExEI7fd414yg8gngq3PMZJS2PxCpkvMlwhlCxk6d5ShXVHv3 -LuH9dBS3BJ7PerZPQ24QeuJdF+n45S2UZgg8jHaaF9AEAYXRgsicVSdxAoGAJI0U -K/bg/awjv0BJwqGsRt/Ukm32TJC5ysAF0HRrajnp5YULChKy9dbtQV7S63QIHIeY -L5+kw/6DvnHV+gULeGjMsjZJXK8Ev7u6+JLivqZYZDYa1iknztvAVegwZxmA61t3 -bantQgNSwerql2U3QQsAH9Vydw0On6RTP2+7WkECgYBWD3u64hBKmAxPkqPotkgI -w/jdOlv8FLHO79+oH1PtKvkzspcYaecKGDm/RNLIXLYnt0AmZEK4qQ4/zDFaR/rc -AhoxK2cKTRltMrhp1ivtFfLggVGogtYNxEnjnsD4KMvH3SjSNdt06YgtZ92++fOp -UsE8Mpf4/G5X7DmcHJHk+w== ------END PRIVATE KEY----- diff --git a/internal/suites/example/compose/envoy/docker-compose.yml b/internal/suites/example/compose/envoy/docker-compose.yml index 3f473b2e8..4941537df 100644 --- a/internal/suites/example/compose/envoy/docker-compose.yml +++ b/internal/suites/example/compose/envoy/docker-compose.yml @@ -5,7 +5,9 @@ services: image: envoyproxy/envoy:v1.25.1 volumes: - ./example/compose/envoy/envoy.yaml:/etc/envoy/envoy.yaml - - ./example/compose/nginx/portal/ssl:/etc/ssl + - ./common/pki:/pki + ports: + - 9901:9901 networks: authelianet: ipv4_address: 192.168.240.100 diff --git a/internal/suites/example/compose/envoy/envoy.yaml b/internal/suites/example/compose/envoy/envoy.yaml index 77783ebe4..7af1e2e90 100644 --- a/internal/suites/example/compose/envoy/envoy.yaml +++ b/internal/suites/example/compose/envoy/envoy.yaml @@ -1,4 +1,10 @@ --- +# Enable the admin interface at http://192.168.240.100:9901/ for debugging. +admin: + address: + socket_address: + address: 0.0.0.0 + port_value: 9901 static_resources: listeners: - name: listener_0 @@ -78,6 +84,13 @@ static_resources: - name: envoy.filters.http.ext_authz typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.ext_authz.v3.ExtAuthz + transport_api_version: v3 + allowed_headers: + patterns: + - exact: authorization + - exact: proxy-authorization + - exact: accept + - exact: cookie http_service: path_prefix: /api/authz/ext-authz/ server_uri: @@ -85,12 +98,6 @@ static_resources: cluster: authelia-backend timeout: 0.25s authorization_request: - allowed_headers: - patterns: - - exact: authorization - - exact: proxy-authorization - - exact: accept - - exact: cookie headers_to_add: - key: X-Forwarded-Proto value: '%REQ(:SCHEME)%' @@ -118,9 +125,9 @@ static_resources: common_tls_context: tls_certificates: - certificate_chain: - filename: /etc/ssl/server.cert + filename: /pki/public.bundle.crt private_key: - filename: /etc/ssl/server.key + filename: /pki/private.pem clusters: - name: authelia-frontend transport_socket_matches: @@ -139,9 +146,9 @@ static_resources: typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.raw_buffer.v3.RawBuffer connect_timeout: 0.25s - type: STRICT_DNS + type: strict_dns dns_lookup_family: V4_ONLY - lb_policy: ROUND_ROBIN + lb_policy: round_robin load_assignment: cluster_name: authelia-frontend endpoints: @@ -172,9 +179,9 @@ static_resources: enableTLS: true - name: authelia-backend connect_timeout: 0.25s - type: LOGICAL_DNS - dns_lookup_family: V4_ONLY - lb_policy: ROUND_ROBIN + type: logical_dns + dns_lookup_family: v4_only + lb_policy: round_robin load_assignment: cluster_name: authelia-backend endpoints: @@ -191,9 +198,9 @@ static_resources: common_tls_context: {} - name: smtp connect_timeout: 0.25s - type: LOGICAL_DNS - dns_lookup_family: V4_ONLY - lb_policy: ROUND_ROBIN + type: logical_dns + dns_lookup_family: v4_only + lb_policy: round_robin load_assignment: cluster_name: smtp endpoints: @@ -205,9 +212,9 @@ static_resources: port_value: 1080 - name: httpbin connect_timeout: 0.25s - type: LOGICAL_DNS - dns_lookup_family: V4_ONLY - lb_policy: ROUND_ROBIN + type: logical_dns + dns_lookup_family: v4_only + lb_policy: round_robin load_assignment: cluster_name: httpbin endpoints: @@ -219,9 +226,9 @@ static_resources: port_value: 8000 - name: nginx-backend connect_timeout: 0.25s - type: LOGICAL_DNS - dns_lookup_family: V4_ONLY - lb_policy: ROUND_ROBIN + type: logical_dns + dns_lookup_family: v4_only + lb_policy: round_robin load_assignment: cluster_name: nginx-backend endpoints: @@ -231,4 +238,15 @@ static_resources: socket_address: address: nginx-backend port_value: 80 +layered_runtime: + layers: + - name: static_layer_0 + static_layer: + envoy: + resource_limits: + listener: + example_listener_name: + connection_limit: 10000 + overload: + global_downstream_max_connections: 50000 ... diff --git a/internal/suites/example/compose/k3d/docker-compose.yml b/internal/suites/example/compose/k3d/docker-compose.yml index a3bfd2fbc..db82d3ba4 100644 --- a/internal/suites/example/compose/k3d/docker-compose.yml +++ b/internal/suites/example/compose/k3d/docker-compose.yml @@ -6,7 +6,7 @@ services: volumes: - './example/kube:/authelia' - './example/kube/authelia/configs/configuration.yml:/configmaps/authelia/configuration.yml' - - './common/ssl:/configmaps/authelia/ssl' + - './common/pki:/configmaps/authelia/ssl' - './example/compose/ldap/ldif:/configmaps/ldap' - './example/compose/nginx/backend:/configmaps/nginx-backend' privileged: true diff --git a/internal/suites/example/compose/nginx/portal/docker-compose.yml b/internal/suites/example/compose/nginx/portal/docker-compose.yml index 517e192fb..4ff9dc3d9 100644 --- a/internal/suites/example/compose/nginx/portal/docker-compose.yml +++ b/internal/suites/example/compose/nginx/portal/docker-compose.yml @@ -5,7 +5,7 @@ services: image: nginx:alpine volumes: - ./example/compose/nginx/portal/nginx.conf:/etc/nginx/nginx.conf - - ./example/compose/nginx/portal/ssl:/etc/ssl + - ./common/pki:/pki networks: authelianet: aliases: diff --git a/internal/suites/example/compose/nginx/portal/nginx.conf b/internal/suites/example/compose/nginx/portal/nginx.conf index e0abc65d3..3d97aeebc 100644 --- a/internal/suites/example/compose/nginx/portal/nginx.conf +++ b/internal/suites/example/compose/nginx/portal/nginx.conf @@ -16,8 +16,8 @@ http { set $backend_endpoint https://authelia-backend:9091; set $metrics_endpoint http://authelia-backend:9959; - ssl_certificate /etc/ssl/server.cert; - ssl_certificate_key /etc/ssl/server.key; + ssl_certificate /pki/public.bundle.crt; + ssl_certificate_key /pki/private.pem; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN"; @@ -128,8 +128,8 @@ http { resolver 127.0.0.11 ipv6=off; set $upstream_endpoint http://nginx-backend; - ssl_certificate /etc/ssl/server.cert; - ssl_certificate_key /etc/ssl/server.key; + ssl_certificate /pki/public.bundle.crt; + ssl_certificate_key /pki/private.pem; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN"; @@ -152,8 +152,8 @@ http { set $upstream_endpoint http://nginx-backend; set $upstream_headers http://httpbin:8000/headers; - ssl_certificate /etc/ssl/server.cert; - ssl_certificate_key /etc/ssl/server.key; + ssl_certificate /pki/public.bundle.crt; + ssl_certificate_key /pki/private.pem; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN"; @@ -295,8 +295,8 @@ http { set $upstream_authelia https://authelia-backend:9091/api/authz/auth-request; set $upstream_endpoint http://oidc-client:8080; - ssl_certificate /etc/ssl/server.cert; - ssl_certificate_key /etc/ssl/server.key; + ssl_certificate /pki/public.bundle.crt; + ssl_certificate_key /pki/private.pem; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN"; @@ -393,8 +393,8 @@ http { resolver 127.0.0.11 ipv6=off; set $upstream_endpoint http://smtp:1080; - ssl_certificate /etc/ssl/server.cert; - ssl_certificate_key /etc/ssl/server.key; + ssl_certificate /pki/public.bundle.crt; + ssl_certificate_key /pki/private.pem; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN"; @@ -415,8 +415,8 @@ http { resolver 127.0.0.11 ipv6=off; set $upstream_endpoint http://duo-api:3000; - ssl_certificate /etc/ssl/server.cert; - ssl_certificate_key /etc/ssl/server.key; + ssl_certificate /pki/public.bundle.crt; + ssl_certificate_key /pki/private.pem; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header X-Frame-Options "SAMEORIGIN"; @@ -434,8 +434,8 @@ http { listen 8080 ssl; server_name _; - ssl_certificate /etc/ssl/server.cert; - ssl_certificate_key /etc/ssl/server.key; + ssl_certificate /pki/public.bundle.crt; + ssl_certificate_key /pki/private.pem; return 301 https://home.example.com:8080/; } diff --git a/internal/suites/example/compose/nginx/portal/ssl/server.cert b/internal/suites/example/compose/nginx/portal/ssl/server.cert deleted file mode 100644 index 0fd2ff140..000000000 --- a/internal/suites/example/compose/nginx/portal/ssl/server.cert +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDEzCCAfugAwIBAgIUJZXxXExVQPJhc8TnlD+uAAYHlvwwDQYJKoZIhvcNAQEL -BQAwGDEWMBQGA1UEAwwNKi5leGFtcGxlLmNvbTAgFw0xOTA5MjYyMDAwMTBaGA8y -MTE5MDkwMjIwMDAxMFowGDEWMBQGA1UEAwwNKi5leGFtcGxlLmNvbTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3DFTAdrxG6iOj5UjSeB5lMjMQQyeYm -OxUvswwwBzmQYPUt0inAJ9QmXJ8i9Fbye8HHYUeqE5zsEfeHir81MiWfhi9oUzJt -u3bmxGLDXYaApejd18hBKITX6MYogmK2lWrl/F9zPYxc2xM/fqWnGg2xwdrMmida -hZjDUfh0rtoz8zqOzJaiiDoFMwNO+NTGmDbeOwBFYOF1OTkS3aJWwJCLZmINUG8h -Z3YPR+SL8CpGGl0xhJYAwXD1AtMlYwAteTILqrqvo2XkGsvuj0mx0w/D0DDpC48g -oSNsRIVTW3Ql3uu+kXDFtkf4I63Ctt85rZk1kX3QtYmS0pRzvmyY/b0CAwEAAaNT -MFEwHQYDVR0OBBYEFMTozK79Kp813+8TstjXRFw1MTE5MB8GA1UdIwQYMBaAFMTo -zK79Kp813+8TstjXRFw1MTE5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL -BQADggEBALf1bJf3qF3m54+q98E6lSE+34yi/rVdzB9reAW1QzvvqdJRtsfjt39R -SznsbmrvCfK4SLyOj9Uhd8Z6bASPPNsUux1XAGN4AqaGmlYI8b7j3LhKCdRBZQ0I -zWgPhocyWwp5VkFe68zR06NHme/2B6eBRFsdd/69DIOv9YnEGUHk3A/9v1zvolt9 -krW57Oz63zWGYXmtPPTD8of/Ya6NKqwonVx1MUQ5QzqH3WySYhRsIYqwUEXm9jt5 -GEM3Nx0phEltaOLXa71nqS/Rhg/5Kod0cFaNoSKb6N93I8bqKKTK0m5wMJ5Fisrm -Pw5+AIar7RT5gHU2DD2/OTb9bXXww8I= ------END CERTIFICATE----- diff --git a/internal/suites/example/compose/nginx/portal/ssl/server.key b/internal/suites/example/compose/nginx/portal/ssl/server.key deleted file mode 100644 index 268a2a1c3..000000000 --- a/internal/suites/example/compose/nginx/portal/ssl/server.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAvcMVMB2vEbqI6PlSNJ4HmUyMxBDJ5iY7FS+zDDAHOZBg9S3S -KcAn1CZcnyL0VvJ7wcdhR6oTnOwR94eKvzUyJZ+GL2hTMm27dubEYsNdhoCl6N3X -yEEohNfoxiiCYraVauX8X3M9jFzbEz9+pacaDbHB2syaJ1qFmMNR+HSu2jPzOo7M -lqKIOgUzA0741MaYNt47AEVg4XU5ORLdolbAkItmYg1QbyFndg9H5IvwKkYaXTGE -lgDBcPUC0yVjAC15Mguquq+jZeQay+6PSbHTD8PQMOkLjyChI2xEhVNbdCXe676R -cMW2R/gjrcK23zmtmTWRfdC1iZLSlHO+bJj9vQIDAQABAoIBAEZvkP/JJOCJwqPn -V3IcbmmilmV4bdi1vByDFgyiDyx4wOSA24+PubjvfFW9XcCgRPuKjDtTj/AhWBHv -B7stfa2lZuNV7/u562mZArA+IAr62Zp0LdIxDV8x3T8gbjVB3HhPYbv0RJZDKTYd -zV6jhfIrVu9mHpoY6ZnodhapCPYIyk/d49KBIHZuAc25CUjMXgTeaVtf0c996036 -UxW6ef33wAOJAvW0RCvbXAJfmBeEq2qQlkjTIlpYx71fhZWexHifi8Ouv3Zonc+1 -/P2Adq5uzYVBT92f9RKHg9QxxNzVrLjSMaxyvUtWQCAQfW0tFIRdqBGsHYsQrFtI -F4yzv8ECgYEA7ntpyN9HD9Z9lYQzPCR73sFCLM+ID99aVij0wHuxK97bkSyyvkLd -7MyTaym3lg1UEqWNWBCLvFULZx7F0Ah6qCzD4ymm3Bj/ADpWWPgljBI0AFml+HHs -hcATmXUrj5QbLyhiP2gmJjajp1o/rgATx6ED66seSynD6JOH8wUhhZUCgYEAy7OA -06PF8GfseNsTqlDjNF0K7lOqd21S0prdwrsJLiVzUlfMM25MLE0XLDUutCnRheeh -IlcuDoBsVTxz6rkvFGD74N+pgXlN4CicsBq5ofK060PbqCQhSII3fmHobrZ9Cr75 -HmBjAxHx998SKaAAGbBbcYGUAp521i1pH5CEPYkCgYEAkUd1Zf0+2RMdZhwm6hh/ -rW+l1I6IoMK70YkZsLipccRNld7Y9LbfYwYtODcts6di9AkOVfueZJiaXbONZfIE -Zrb+jkAteh9wGL9xIrnohbABJcV3Kiaco84jInUSmGDtPokncOENfHIEuEpuSJ2b -bx1TuhmAVuGWivR0+ULC7RECgYEAgS0cDRpWc9Xzh9Cl7+PLsXEvdWNpPsL9OsEq -0Ep7z9+/+f/jZtoTRCS/BTHUpDvAuwHglT5j3p5iFMt5VuiIiovWLwynGYwrbnNS -qfrIrYKUaH1n1oDS+oBZYLQGCe9/7EifAjxtjYzbvSyg//SPG7tSwfBCREbpZXj2 -qSWkNsECgYA/mCDzCTlrrWPuiepo6kTmN+4TnFA+hJI6NccDVQ+jvbqEdoJ4SW4L -zqfZSZRFJMNpSgIqkQNRPJqMP0jQ5KRtJrjMWBnYxktwKz9fDg2R2MxdFgMF2LH2 -HEMMhFHlv8NDjVOXh1KwRoltNGVWYsSrD9wKU9GhRCEfmNCGrvBcEg== ------END RSA PRIVATE KEY----- diff --git a/internal/suites/example/kube/authelia/configs/configuration.yml b/internal/suites/example/kube/authelia/configs/configuration.yml index 19eec843f..165f79a93 100644 --- a/internal/suites/example/kube/authelia/configs/configuration.yml +++ b/internal/suites/example/kube/authelia/configs/configuration.yml @@ -8,8 +8,8 @@ default_redirection_url: https://home.example.com:8080 server: port: 443 tls: - certificate: /config/ssl/cert.pem - key: /config/ssl/key.pem + certificate: /config/ssl/public.backend.crt + key: /config/ssl/private.backend.pem log: level: debug diff --git a/internal/suites/suite_cli_test.go b/internal/suites/suite_cli_test.go index cb7229f63..f214d1301 100644 --- a/internal/suites/suite_cli_test.go +++ b/internal/suites/suite_cli_test.go @@ -402,7 +402,7 @@ func (s *CLISuite) TestShouldGenerateCertificateRSAWithNotBefore() { 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, "Error: failed to parse not before: parsing time \"Jan\" as \"Jan 2 15:04:05 2006\": cannot parse \"\" as \"2\"") + s.Assert().Contains(output, "Error: failed to parse not before: failed to find a suitable time layout for time 'Jan'") } func (s *CLISuite) TestShouldGenerateCertificateRSAWith4096Bits() { @@ -555,7 +555,7 @@ func (s *CLISuite) TestShouldGenerateCertificateEd25519() { 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\"") + s.Assert().Contains(output, "Error: failed to parse not before: failed to find a suitable time layout for time 'invalid'") } func (s *CLISuite) TestShouldFailGenerateCertificateECDSA() { diff --git a/internal/utils/const.go b/internal/utils/const.go index cb02b5459..3ce72025f 100644 --- a/internal/utils/const.go +++ b/internal/utils/const.go @@ -70,9 +70,22 @@ const ( ) var ( + // StandardTimeLayouts is the set of standard time layouts used with ParseTimeString. + StandardTimeLayouts = []string{ + "Jan 2 15:04:05 2006", + time.DateTime, + time.RFC3339, + time.RFC1123Z, + time.RubyDate, + time.ANSIC, + time.DateOnly, + } + standardDurationUnits = []string{"ns", "us", "µs", "μs", "ms", "s", "m", "h"} - reDurationSeconds = regexp.MustCompile(`^\d+$`) - reDurationStandard = regexp.MustCompile(`(?P[1-9]\d*?)(?P[^\d\s]+)`) + + reOnlyNumeric = regexp.MustCompile(`^\d+$`) + reDurationStandard = regexp.MustCompile(`(?P[1-9]\d*?)(?P[^\d\s]+)`) + reNumeric = regexp.MustCompile(`\d+`) ) // Duration unit types. diff --git a/internal/utils/crypto.go b/internal/utils/crypto.go index 17481a5cf..425b5f10b 100644 --- a/internal/utils/crypto.go +++ b/internal/utils/crypto.go @@ -307,7 +307,7 @@ func NewX509CertPool(directory string) (certPool *x509.CertPool, warnings []erro } // WriteCertificateBytesToPEM writes a certificate/csr to a file in the PEM format. -func WriteCertificateBytesToPEM(cert []byte, path string, csr bool) (err error) { +func WriteCertificateBytesToPEM(path string, csr bool, certs ...[]byte) (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) @@ -318,10 +318,12 @@ func WriteCertificateBytesToPEM(cert []byte, path string, csr bool) (err error) blockType = BlockTypeCertificateRequest } - if err = pem.Encode(out, &pem.Block{Bytes: cert, Type: blockType}); err != nil { - _ = out.Close() + for _, cert := range certs { + if err = pem.Encode(out, &pem.Block{Bytes: cert, Type: blockType}); err != nil { + _ = out.Close() - return err + return err + } } return out.Close() @@ -545,7 +547,7 @@ func X509ParseKeyUsage(keyUsages []string, ca bool) (keyUsage x509.KeyUsage) { func X509ParseExtendedKeyUsage(extKeyUsages []string, ca bool) (extKeyUsage []x509.ExtKeyUsage) { if len(extKeyUsages) == 0 { if ca { - extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny} + extKeyUsage = []x509.ExtKeyUsage{} } else { extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} } diff --git a/internal/utils/crypto_test.go b/internal/utils/crypto_test.go index dc7889996..4104a3ab5 100644 --- a/internal/utils/crypto_test.go +++ b/internal/utils/crypto_test.go @@ -52,9 +52,9 @@ func TestShouldNotReturnErrWhenX509DirectoryExist(t *testing.T) { } func TestShouldReadCertsFromDirectoryButNotKeys(t *testing.T) { - pool, warnings, errors := NewX509CertPool("../suites/common/ssl/") + pool, warnings, errors := NewX509CertPool("../suites/common/pki/") assert.NotNil(t, pool) - require.Len(t, errors, 1) + require.Len(t, errors, 2) if runtime.GOOS == "windows" { require.Len(t, warnings, 1) @@ -63,7 +63,8 @@ func TestShouldReadCertsFromDirectoryButNotKeys(t *testing.T) { assert.Len(t, warnings, 0) } - assert.EqualError(t, errors[0], "could not import certificate key.pem") + assert.EqualError(t, errors[0], "could not import certificate private.backend.pem") + assert.EqualError(t, errors[1], "could not import certificate private.pem") } func TestShouldGenerateCertificateAndPersistIt(t *testing.T) { @@ -441,7 +442,7 @@ func TestX509ParseExtendedKeyUsage(t *testing.T) { expected []x509.ExtKeyUsage }{ {"ShouldParseDefault", nil, false, []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}}, - {"ShouldParseDefaultCA", nil, true, []x509.ExtKeyUsage{x509.ExtKeyUsageAny}}, + {"ShouldParseDefaultCA", nil, true, []x509.ExtKeyUsage{}}, {"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}}, diff --git a/internal/utils/time.go b/internal/utils/time.go index 4844e108e..c044f899a 100644 --- a/internal/utils/time.go +++ b/internal/utils/time.go @@ -3,6 +3,7 @@ package utils import ( "fmt" "strconv" + "strings" "time" ) @@ -12,44 +13,75 @@ func StandardizeDurationString(input string) (output string, err error) { return "0s", nil } - matches := reDurationStandard.FindAllStringSubmatch(input, -1) + matches := reDurationStandard.FindAllStringSubmatch(strings.ReplaceAll(input, " ", ""), -1) if len(matches) == 0 { return "", fmt.Errorf("could not parse '%s' as a duration", input) } - var d int + var ( + o string + q int + ) for _, match := range matches { - if d, err = strconv.Atoi(match[1]); err != nil { - return "", fmt.Errorf("could not parse the numeric portion of '%s' in duration string '%s': %w", match[0], input, err) + if q, err = strconv.Atoi(match[1]); err != nil { + return "", err } - unit := match[2] - - switch { - case IsStringInSlice(unit, standardDurationUnits): - output += fmt.Sprintf("%d%s", d, unit) - case unit == DurationUnitDays: - output += fmt.Sprintf("%dh", d*HoursInDay) - case unit == DurationUnitWeeks: - output += fmt.Sprintf("%dh", d*HoursInWeek) - case unit == DurationUnitMonths: - output += fmt.Sprintf("%dh", d*HoursInMonth) - case unit == DurationUnitYears: - output += fmt.Sprintf("%dh", d*HoursInYear) - default: - return "", fmt.Errorf("could not parse the units portion of '%s' in duration string '%s': the unit '%s' is not valid", match[0], input, unit) + if o, err = standardizeQuantityAndUnits(q, match[2]); err != nil { + return "", fmt.Errorf("could not parse the units portion of '%s' in duration string '%s': %w", match[0], input, err) } + + output += o } return output, nil } +func standardizeQuantityAndUnits(qty int, unit string) (output string, err error) { + switch { + case IsStringInSlice(unit, standardDurationUnits): + return fmt.Sprintf("%d%s", qty, unit), nil + case len(unit) == 1: + switch unit { + case DurationUnitDays: + return fmt.Sprintf("%dh", qty*HoursInDay), nil + case DurationUnitWeeks: + return fmt.Sprintf("%dh", qty*HoursInWeek), nil + case DurationUnitMonths: + return fmt.Sprintf("%dh", qty*HoursInMonth), nil + case DurationUnitYears: + return fmt.Sprintf("%dh", qty*HoursInYear), nil + } + default: + switch unit { + case "millisecond", "milliseconds": + return fmt.Sprintf("%dms", qty), nil + case "second", "seconds": + return fmt.Sprintf("%ds", qty), nil + case "minute", "minutes": + return fmt.Sprintf("%dm", qty), nil + case "hour", "hours": + return fmt.Sprintf("%dh", qty), nil + case "day", "days": + return fmt.Sprintf("%dh", qty*HoursInDay), nil + case "week", "weeks": + return fmt.Sprintf("%dh", qty*HoursInWeek), nil + case "month", "months": + return fmt.Sprintf("%dh", qty*HoursInMonth), nil + case "year", "years": + return fmt.Sprintf("%dh", qty*HoursInYear), nil + } + } + + return "", fmt.Errorf("the unit '%s' is not valid", unit) +} + // ParseDurationString standardizes a duration string with StandardizeDurationString then uses time.ParseDuration to // convert it into a time.Duration. func ParseDurationString(input string) (duration time.Duration, err error) { - if reDurationSeconds.MatchString(input) { + if reOnlyNumeric.MatchString(input) { var seconds int if seconds, err = strconv.Atoi(input); err != nil { @@ -68,6 +100,50 @@ func ParseDurationString(input string) (duration time.Duration, err error) { return time.ParseDuration(out) } +// ParseTimeString attempts to parse a string with several time formats. +func ParseTimeString(input string) (t time.Time, err error) { + return ParseTimeStringWithLayouts(input, StandardTimeLayouts) +} + +// ParseTimeStringWithLayouts attempts to parse a string with several time formats. The format with the most matching +// characters is returned. +func ParseTimeStringWithLayouts(input string, layouts []string) (match time.Time, err error) { + _, match, err = matchParseTimeStringWithLayouts(input, layouts) + + return +} + +func matchParseTimeStringWithLayouts(input string, layouts []string) (index int, match time.Time, err error) { + if reOnlyNumeric.MatchString(input) { + var u int64 + + if u, err = strconv.ParseInt(input, 10, 64); err != nil { + return -999, match, fmt.Errorf("time value was detected as an integer but the integer could not be parsed: %w", err) + } + + switch { + case u > 32503554000000: // 2999-12-31 00:00:00 in unix time (milliseconds). + return -3, time.UnixMicro(u), nil + case u > 946645200000: // 2000-01-01 00:00:00 in unix time (milliseconds). + return -2, time.UnixMilli(u), nil + default: + return -1, time.Unix(u, 0), nil + } + } + + var layout string + + for index, layout = range layouts { + if match, err = time.Parse(layout, input); err == nil { + if len(match.Format(layout))-len(input) == 0 { + return index, match, nil + } + } + } + + return -998, time.UnixMilli(0), fmt.Errorf("failed to find a suitable time layout for time '%s'", input) +} + // UnixNanoTimeToMicrosoftNTEpoch converts a unix timestamp in nanosecond format to win32 epoch format. func UnixNanoTimeToMicrosoftNTEpoch(nano int64) (t uint64) { return uint64(nano/100) + timeUnixEpochAsMicrosoftNTEpoch diff --git a/internal/utils/time_test.go b/internal/utils/time_test.go index 4cd651c9c..39b011fa6 100644 --- a/internal/utils/time_test.go +++ b/internal/utils/time_test.go @@ -1,63 +1,112 @@ package utils import ( + "fmt" + "strings" "testing" "time" "github.com/stretchr/testify/assert" ) -func TestParseDurationString_ShouldParseDurationString(t *testing.T) { - duration, err := ParseDurationString("1h") +func TestParseDurationString(t *testing.T) { + testCases := []struct { + name string + have []string + raw bool + expected time.Duration + err string + }{ + {"ShouldParseStringsForMillisecond", []string{"%d ms", "%d millisecond", "%d milliseconds"}, false, time.Millisecond, ""}, + {"ShouldParseStringsForSecond", []string{"%d s", "%d second", "%d seconds"}, false, time.Second, ""}, + {"ShouldParseStringsForMinute", []string{"%d m", "%d minute", "%d minutes"}, false, time.Minute, ""}, + {"ShouldParseStringsForHour", []string{"%d h", "%d hour", "%d hours"}, false, time.Hour, ""}, + {"ShouldParseStringsForDay", []string{"%d d", "%d day", "%d days"}, false, time.Hour * HoursInDay, ""}, + {"ShouldParseStringsForWeek", []string{"%d w", "%d week", "%d weeks"}, false, time.Hour * HoursInWeek, ""}, + {"ShouldParseStringsForMonth", []string{"%d M", "%d month", "%d months"}, false, time.Hour * HoursInMonth, ""}, + {"ShouldParseStringsForYear", []string{"%d y", "%d year", "%d years"}, false, time.Hour * HoursInYear, ""}, + {"ShouldParseStringsDecimals", []string{"100"}, true, time.Second * 100, ""}, + {"ShouldParseStringsDecimalNull", []string{""}, true, time.Second * 0, ""}, + } - assert.NoError(t, err) - assert.Equal(t, 60*time.Minute, duration) -} + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for _, f := range tc.have { + if tc.raw { + t.Run(f, func(t *testing.T) { + actual, actualErr := ParseDurationString(f) -func TestParseDurationString_ShouldParseBlankString(t *testing.T) { - duration, err := ParseDurationString("") + if tc.err == "" { + assert.NoError(t, actualErr) + assert.Equal(t, tc.expected, actual) + } else { + assert.EqualError(t, actualErr, tc.err) + } + }) + } else { + for _, d := range []int{1, 5, 20} { + input := fmt.Sprintf(f, d) - assert.NoError(t, err) - assert.Equal(t, time.Second*0, duration) -} + inputNoSpace := strings.ReplaceAll(input, " ", "") -func TestParseDurationString_ShouldParseDurationStringAllUnits(t *testing.T) { - duration, err := ParseDurationString("1y") + t.Run(inputNoSpace, func(t *testing.T) { + t.Run("WithSpaces", func(t *testing.T) { + actual, actualErr := ParseDurationString(input) - assert.NoError(t, err) - assert.Equal(t, time.Hour*24*365, duration) + if tc.err == "" { + assert.NoError(t, actualErr) + assert.Equal(t, tc.expected*time.Duration(d), actual) + } else { + assert.EqualError(t, actualErr, tc.err) + } - duration, err = ParseDurationString("1M") + t.Run("LeadingZeros", func(t *testing.T) { + inputActual := reNumeric.ReplaceAllStringFunc(input, func(s string) string { + return "000" + s + }) - assert.NoError(t, err) - assert.Equal(t, time.Hour*24*30, duration) + actual, actualErr := ParseDurationString(inputActual) - duration, err = ParseDurationString("1w") + if tc.err == "" { + assert.NoError(t, actualErr) + assert.Equal(t, tc.expected*time.Duration(d), actual) + } else { + assert.EqualError(t, actualErr, tc.err) + } + }) + }) - assert.NoError(t, err) - assert.Equal(t, time.Hour*24*7, duration) + t.Run("WithoutSpaces", func(t *testing.T) { + actual, actualErr := ParseDurationString(inputNoSpace) - duration, err = ParseDurationString("1d") + if tc.err == "" { + assert.NoError(t, actualErr) + assert.Equal(t, tc.expected*time.Duration(d), actual) + } else { + assert.EqualError(t, actualErr, tc.err) + } - assert.NoError(t, err) - assert.Equal(t, time.Hour*24, duration) + t.Run("LeadingZeros", func(t *testing.T) { + inputActual := reNumeric.ReplaceAllStringFunc(inputNoSpace, func(s string) string { + return "000" + s + }) - duration, err = ParseDurationString("1h") + actual, actualErr := ParseDurationString(inputActual) - assert.NoError(t, err) - assert.Equal(t, time.Hour, duration) - - duration, err = ParseDurationString("1s") - - assert.NoError(t, err) - assert.Equal(t, time.Second, duration) -} - -func TestParseDurationString_ShouldParseSecondsString(t *testing.T) { - duration, err := ParseDurationString("100") - - assert.NoError(t, err) - assert.Equal(t, 100*time.Second, duration) + if tc.err == "" { + assert.NoError(t, actualErr) + assert.Equal(t, tc.expected*time.Duration(d), actual) + } else { + assert.EqualError(t, actualErr, tc.err) + } + }) + }) + }) + } + } + } + }) + } } func TestParseDurationString_ShouldNotParseDurationStringWithOutOfOrderQuantitiesAndUnits(t *testing.T) { @@ -74,18 +123,11 @@ func TestParseDurationString_ShouldNotParseBadDurationString(t *testing.T) { assert.Equal(t, time.Duration(0), duration) } -func TestParseDurationString_ShouldParseDurationStringWithMultiValueUnits(t *testing.T) { - duration, err := ParseDurationString("10ms") +func TestParseDurationString_ShouldNotParseBadDurationStringAlt(t *testing.T) { + duration, err := ParseDurationString("10abcxyz") - assert.NoError(t, err) - assert.Equal(t, time.Duration(10)*time.Millisecond, duration) -} - -func TestParseDurationString_ShouldParseDurationStringWithLeadingZero(t *testing.T) { - duration, err := ParseDurationString("005h") - - assert.NoError(t, err) - assert.Equal(t, time.Duration(5)*time.Hour, duration) + assert.EqualError(t, err, "could not parse the units portion of '10abcxyz' in duration string '10abcxyz': the unit 'abcxyz' is not valid") + assert.Equal(t, time.Duration(0), duration) } func TestParseDurationString_ShouldParseMultiUnitValues(t *testing.T) { @@ -130,3 +172,35 @@ func TestShouldConvertKnownUnixNanoTimeToKnownWin32Epoch(t *testing.T) { assert.Equal(t, win32Epoch, UnixNanoTimeToMicrosoftNTEpoch(exampleNanoTime)) assert.Equal(t, timeUnixEpochAsMicrosoftNTEpoch, UnixNanoTimeToMicrosoftNTEpoch(0)) } + +func TestParseTimeString(t *testing.T) { + testCases := []struct { + name string + have string + index int + expected time.Time + err string + }{ + {"ShouldParseIntegerAsUnix", "1675899060", -1, time.Unix(1675899060, 0), ""}, + {"ShouldParseIntegerAsUnixMilli", "1675899060000", -2, time.Unix(1675899060, 0), ""}, + {"ShouldParseIntegerAsUnixMicro", "1675899060000000", -3, time.Unix(1675899060, 0), ""}, + {"ShouldNotParseSuperLargeInteger", "9999999999999999999999999999999999999999", -999, time.Unix(0, 0), "time value was detected as an integer but the integer could not be parsed: strconv.ParseInt: parsing \"9999999999999999999999999999999999999999\": value out of range"}, + {"ShouldParseSimpleTime", "Jan 2 15:04:05 2006", 0, time.Unix(1136214245, 0), ""}, + {"ShouldNotParseInvalidTime", "abc", -998, time.Unix(0, 0), "failed to find a suitable time layout for time 'abc'"}, + {"ShouldMatchDate", "2020-05-01", 6, time.Unix(1588291200, 0), ""}, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + index, actual, err := matchParseTimeStringWithLayouts(tc.have, StandardTimeLayouts) + + if tc.err == "" { + assert.NoError(t, err) + assert.Equal(t, tc.index, index) + assert.Equal(t, tc.expected.UnixNano(), actual.UnixNano()) + } else { + assert.EqualError(t, err, tc.err) + } + }) + } +}