Merge remote-tracking branch 'origin/master' into refactor-trust-provider

pull/4713/head
James Elliott 2023-03-03 08:38:39 +11:00
commit 3b72667d98
No known key found for this signature in database
GPG Key ID: 0F1C4A096E857E49
93 changed files with 1976 additions and 1562 deletions

View File

@ -15,6 +15,8 @@ if [[ ! "${BUILDKITE_BRANCH}" =~ ^(v.*) ]] && [[ "${BUILDKITE_COMMAND_EXIT_STATU
NAME="UnitTest"
if [[ "${SUITE}" != "" ]]; then
NAME=${SUITE}
go tool covdata percent -i=coverage
go tool covdata textfmt -i=coverage -o coverage.txt
fi
if [[ "${BUILDKITE_AGENT_META_DATA_CODECOV}" == "verbose" ]]; then
BUILDKITE_AGENT_META_DATA_CODECOV="-v"
@ -23,7 +25,7 @@ if [[ ! "${BUILDKITE_BRANCH}" =~ ^(v.*) ]] && [[ "${BUILDKITE_COMMAND_EXIT_STATU
if [[ "${BUILDKITE_LABEL}" =~ ":selenium:" ]]; then
cd web && pnpm report
fi
codecov -Z -c -f '!Dockerfile*' -f '!*.go' -f '!*.zst' -n ${NAME} -F frontend "${BUILDKITE_AGENT_META_DATA_CODECOV}"
codecov -Z -c -f '!Dockerfile*' -f '!*.go' -f '!*.tar' -f '!*.zst' -n ${NAME} -F frontend "${BUILDKITE_AGENT_META_DATA_CODECOV}"
fi
fi

View File

@ -31,6 +31,7 @@ fi
if [[ "${BUILDKITE_LABEL}" =~ ":selenium:" ]]; then
DEFAULT_ARCH=coverage
echo "--- :docker: Extract and load build container"
mkdir coverage
buildkite-agent artifact download "authelia-image-${DEFAULT_ARCH}*" .
if [[ "${SUITE}" == "Kubernetes" ]]; then
zstd -d authelia-image-coverage.tar.zst --stdout > ./internal/suites/example/kube/authelia-image-${DEFAULT_ARCH}.tar

View File

@ -133,7 +133,9 @@ body:
id: logs
attributes:
label: Logs (Authelia)
description: Provide complete debug logs (the template will automatically put this content in a code block)
description: |
Provide complete logs with the log level set to debug or trace. Complete means from application start until the
issue occurring. The template will automatically put this content in a code block so you can just paste it.
render: shell
validations:
required: true

View File

@ -15,7 +15,7 @@ RUN yarn global add pnpm && \
# =======================================
# ===== Build image for the backend =====
# =======================================
FROM golang:1.20.0-alpine AS builder-backend
FROM golang:1.20.1-alpine AS builder-backend
WORKDIR /go/src/app
@ -39,9 +39,9 @@ RUN \
mv api internal/server/public_html/api && \
cd cmd/authelia && \
chmod 0666 /go/src/app/.healthcheck.env && \
echo ">> Starting go build (coverage via go test)..." && \
CGO_ENABLED=1 CGO_CPPFLAGS="-D_FORTIFY_SOURCE=2 -fstack-protector-strong" CGO_LDFLAGS="-Wl,-z,relro,-z,now" go test -c --tags coverage -covermode=atomic \
-ldflags "${LDFLAGS_EXTRA}" -o authelia -coverpkg github.com/authelia/authelia/...
echo ">> Starting go build (coverage via -cover)..." && \
CGO_ENABLED=1 CGO_CPPFLAGS="-D_FORTIFY_SOURCE=2 -fstack-protector-strong" CGO_LDFLAGS="-Wl,-z,relro,-z,now" go build -cover -covermode=atomic \
-ldflags "${LDFLAGS_EXTRA}" -o authelia
# ===================================
# ===== Authelia official image =====
@ -59,7 +59,8 @@ EXPOSE 9091
VOLUME /config
ENV PATH="/app:${PATH}" \
GOCOVERDIR="/authelia/coverage/" \
X_AUTHELIA_CONFIG="/config/configuration.yml"
CMD ["authelia", "-test.coverprofile=/authelia/coverage.txt", "COVERAGE"]
CMD ["authelia"]
HEALTHCHECK --interval=30s --timeout=3s CMD /app/healthcheck.sh

View File

@ -13,7 +13,7 @@ RUN yarn install --frozen-lockfile && yarn build
# =======================================
# ===== Build image for the backend =====
# =======================================
FROM golang:1.20.0-alpine AS builder-backend
FROM golang:1.20.1-alpine AS builder-backend
WORKDIR /go/src/app

View File

@ -76,6 +76,14 @@ paths:
schema:
$ref: '#/components/schemas/handlers.configuration.PasswordPolicyConfigurationBody'
/api/health:
head:
tags:
- State
summary: Application Health
description: The health check endpoint provides information about the health of Authelia.
responses:
"200":
description: Successful Operation
get:
tags:
- State

View File

@ -95,7 +95,9 @@ body:
id: logs
attributes:
label: Logs (Authelia)
description: Provide complete debug logs (the template will automatically put this content in a code block)
description: |
Provide complete logs with the log level set to debug or trace. Complete means from application start until the
issue occurring. The template will automatically put this content in a code block so you can just paste it.
render: shell
validations:
required: true

View File

@ -7,5 +7,5 @@
package cmd
const (
versionSwaggerUI = "4.15.5"
versionSwaggerUI = "4.17.0"
)

View File

@ -1,43 +0,0 @@
// +build coverage
package main
import (
"os"
"os/signal"
"strings"
"syscall"
"testing"
)
func TestCoverage(t *testing.T) {
var (
args []string
)
for _, arg := range os.Args {
switch {
case strings.HasPrefix(arg, "COVERAGE"):
case strings.HasPrefix(arg, "-test"):
default:
args = append(args, arg)
}
}
waitCh := make(chan int, 1)
os.Args = args
go func() {
main()
close(waitCh)
}()
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGHUP)
select {
case <-signalCh:
return
case <-waitCh:
return
}
}

View File

@ -75,7 +75,8 @@ level to `debug` or `trace` this will generate large amount of log entries. Admi
they rotate and/or truncate the logs over time to prevent significant long-term disk usage.
If you include the value `%d` in the filename it will replace this value with a date time indicative of the time
the logger was initialized using `2006-02-01T150405Z` as the format.
the logger was initialized using [RFC3339](https://datatracker.ietf.org/doc/html/rfc3339) as the format which is
represented as `2006-01-02T15:04:05Z07:00` in go.
#### File Path Examples

View File

@ -32,6 +32,10 @@ This example makes the following assumptions:
* __Authelia Root URL:__ `https://auth.example.com`
* __Client ID:__ `gitea`
* __Client Secret:__ `insecure_secret`
* __Authentication Name (Gitea):__ `authelia`:
* This option determines the redirect URI in the format of
`https://gitea.example.com/user/oauth2/<Authentication Name>/callback`.
This means if you change this value you need to update the redirect URI.
## Configuration

View File

@ -68,7 +68,7 @@ services:
volumes:
- ${PWD}/data/nginx-proxy-manager/data:/data
- ${PWD}/data/nginx-proxy-manager/letsencrypt:/etc/letsencrypt
- ${PWD}/data/nginx/snippets:/config/nginx/snippets:ro
- ${PWD}/data/nginx/snippets:/snippets:ro
environment:
TZ: 'Australia/Melbourne'
authelia:

View File

@ -42,22 +42,67 @@ bootstrapping *Authelia*.
### SWAG Caveat
One current caveat of the [SWAG] implementation is that it serves Authelia as a subpath for each domain. We
*__strongly recommend__* instead of using the out of the box method and guide for [SWAG] that you follow the
[NGINX](nginx.md) guide (which *can be used* with [SWAG]) and run Authelia as it's own subdomain.
One current caveat of the [SWAG] implementation is that it serves Authelia as a subpath for each domain by default. We
*__strongly recommend__* instead of using the defaults that you configure Authelia as a subdomain if possible.
This is partly because Webauthn requires that the domain is an exact match when registering and authenticating and it is
There are two potential ways to achieve this:
1. Adjust the default `authelia-server.conf` as per the included directions.
2. Use the supplementary configuration snippets provided officially by Authelia.
This is partly because WebAuthn requires that the domain is an exact match when registering and authenticating and it is
possible that due to web standards this will never change.
In addition this represents a bad user experience in some instances such as:
- Users sometimes visit the `https://app.example.com/authelia` URL which doesn't automatically redirect the user to
`https://app.example.com` (if they visit `https://app.example.com` then they'll be redirected to authenticate then
redirected back to their original URL).
- Administrators may wish to setup OpenID Connect 1.0 in which case it also doesn't represent a good user experience.
- Users sometimes visit the `https://app.example.com/authelia` URL which doesn't automatically redirect the user to
`https://app.example.com` (if they visit `https://app.example.com` then they'll be redirected to authenticate then
redirected back to their original URL).
- Administrators may wish to setup [OpenID Connect 1.0](../../configuration/identity-providers/open-id-connect.md) in
which case it also doesn't represent a good user experience as the `issuer` will be
`https://app.example.com/authelia` for example
- Using the [SWAG] default configurations are more difficult to support as our specific familiarity is with our own
example snippets
Taking these factors into consideration we're adapting our [SWAG] guide to use what we consider best for the users and
most easily supported. Users who wish to use the [SWAG] guide are free to do so but may not receive the same support.
#### Option 1: Adjusting the Default Configuration
Open the generated `authelia-server.conf`. Adjust the following sections. There are two snippets, one before and one
after. The only lines that change are the `set $authelia_backend` lines, and this configuration assumes you're
serving Authelia at `auth.example.com`.
```nginx
## Set $authelia_backend to route requests to the current domain by default
set $authelia_backend $http_host;
## In order for Webauthn to work with multiple domains authelia must operate on a separate subdomain
## To use authelia on a separate subdomain:
## * comment the $authelia_backend line above
## * rename /config/nginx/proxy-confs/authelia.conf.sample to /config/nginx/proxy-confs/authelia.conf
## * make sure that your dns has a cname set for authelia
## * uncomment the $authelia_backend line below and change example.com to your domain
## * restart the swag container
#set $authelia_backend authelia.example.com;
return 302 https://$authelia_backend/authelia/?rd=$target_url;
```
```nginx
## Set $authelia_backend to route requests to the current domain by default
# set $authelia_backend $http_host;
## In order for Webauthn to work with multiple domains authelia must operate on a separate subdomain
## To use authelia on a separate subdomain:
## * comment the $authelia_backend line above
## * rename /config/nginx/proxy-confs/authelia.conf.sample to /config/nginx/proxy-confs/authelia.conf
## * make sure that your dns has a cname set for authelia
## * uncomment the $authelia_backend line below and change example.com to your domain
## * restart the swag container
set $authelia_backend auth.example.com;
return 302 https://$authelia_backend/authelia/?rd=$target_url;
```
#### Option 2: Using the Authelia Supplementary Configuration Snippets
See standard [NGINX](nginx.md) guide (which *can be used* with [SWAG]) and run Authelia as it's own subdomain.
## Trusted Proxies
@ -102,6 +147,8 @@ services:
- '443:443'
volumes:
- ${PWD}/data/swag:/config
#- ${PWD}/data/nginx/snippets:/snippets:ro
## Uncomment the above line if you want to use the Authelia configuration snippets.
environment:
PUID: '1000'
PGID: '1000'

View File

@ -35,31 +35,32 @@ authelia crypto certificate ecdsa generate --help
### Options
```
--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
--bundles strings enables generating bundles options are 'chain' and 'privkey-chain'
--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.bundle.chain string name of the file to export the certificate chain PEM bundle to when the --bundles flag includes 'chain' (default "public.chain.pem")
--file.bundle.priv-chain string name of the file to export the certificate chain and private key PEM bundle to when the --bundles flag includes 'priv-chain' (default "private.chain.pem")
--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-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

View File

@ -35,30 +35,31 @@ authelia crypto certificate ed25519 request --help
### Options
```
--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
--bundles strings enables generating bundles options are 'chain' and 'privkey-chain'
--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.bundle.chain string name of the file to export the certificate chain PEM bundle to when the --bundles flag includes 'chain' (default "public.chain.pem")
--file.bundle.priv-chain string name of the file to export the certificate chain and private key PEM bundle to when the --bundles flag includes 'priv-chain' (default "private.chain.pem")
--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-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

View File

@ -35,31 +35,32 @@ authelia crypto certificate rsa generate --help
### Options
```
-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
-b, --bits int number of RSA bits for the certificate (default 2048)
--bundles strings enables generating bundles options are 'chain' and 'privkey-chain'
--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.bundle.chain string name of the file to export the certificate chain PEM bundle to when the --bundles flag includes 'chain' (default "public.chain.pem")
--file.bundle.priv-chain string name of the file to export the certificate chain and private key PEM bundle to when the --bundles flag includes 'priv-chain' (default "private.chain.pem")
--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-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

View File

@ -45,7 +45,7 @@ services:
- TZ=Australia/Melbourne
traefik:
image: traefik:v2.9.6
image: traefik:v2.9.8
container_name: traefik
volumes:
- ./traefik:/etc/traefik

View File

@ -32,7 +32,7 @@ services:
- TZ=Australia/Melbourne
traefik:
image: traefik:v2.9.6
image: traefik:v2.9.8
container_name: traefik
volumes:
- ./traefik:/etc/traefik

36
go.mod
View File

@ -7,28 +7,33 @@ require (
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/deckarep/golang-set/v2 v2.1.0
github.com/duosecurity/duo_api_golang v0.0.0-20230203160531-b221c950c2b0
github.com/fasthttp/router v1.4.16
github.com/fasthttp/router v1.4.17
github.com/fasthttp/session/v2 v2.4.16
github.com/fsnotify/fsnotify v1.6.0
github.com/go-asn1-ber/asn1-ber v1.5.4
github.com/go-crypt/crypt v0.2.5
github.com/go-crypt/crypt v0.2.6
github.com/go-ldap/ldap/v3 v3.4.4
github.com/go-rod/rod v0.112.5
github.com/go-rod/rod v0.112.6
github.com/go-sql-driver/mysql v1.7.0
github.com/go-webauthn/webauthn v0.7.0
github.com/golang-jwt/jwt/v4 v4.4.3
github.com/go-webauthn/webauthn v0.7.1
github.com/golang-jwt/jwt/v4 v4.5.0
github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.0
github.com/hashicorp/go-retryablehttp v0.7.2
github.com/jackc/pgx/v5 v5.2.0
github.com/jackc/pgx/v5 v5.3.1
github.com/jmoiron/sqlx v1.3.5
github.com/knadh/koanf v1.5.0
github.com/knadh/koanf/parsers/yaml v0.1.0
github.com/knadh/koanf/providers/confmap v0.1.0
github.com/knadh/koanf/providers/env v0.1.0
github.com/knadh/koanf/providers/posflag v0.1.0
github.com/knadh/koanf/providers/rawbytes v0.1.0
github.com/knadh/koanf/v2 v2.0.0
github.com/mattn/go-sqlite3 v1.14.16
github.com/mitchellh/mapstructure v1.5.0
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
github.com/ory/fosite v0.44.0
github.com/ory/herodot v0.9.13
github.com/ory/x v0.0.535
github.com/ory/x v0.0.542
github.com/otiai10/copy v1.9.0
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.4.0
@ -36,11 +41,11 @@ require (
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.1
github.com/stretchr/testify v1.8.2
github.com/trustelem/zxcvbn v1.0.1
github.com/valyala/fasthttp v1.44.0
github.com/wneessen/go-mail v0.3.8
golang.org/x/net v0.6.0
golang.org/x/net v0.7.0
golang.org/x/sync v0.1.0
golang.org/x/term v0.5.0
golang.org/x/text v0.7.0
@ -65,9 +70,9 @@ require (
github.com/ecordell/optgen v0.0.6 // indirect
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/fxamacker/cbor/v2 v2.4.0 // indirect
github.com/go-crypt/x v0.1.12 // indirect
github.com/go-crypt/x v0.1.13 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-webauthn/revoke v0.1.6 // indirect
github.com/go-webauthn/revoke v0.1.9 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-tpm v0.3.3 // indirect
@ -76,9 +81,10 @@ require (
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jandelgado/gcov2lcov v1.0.5 // indirect
github.com/klauspost/compress v1.15.9 // indirect
github.com/knadh/koanf/maps v0.1.1 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/goveralls v0.0.11 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
@ -95,7 +101,7 @@ require (
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
@ -108,7 +114,7 @@ require (
github.com/ysmood/goob v0.4.0 // indirect
github.com/ysmood/gson v0.7.3 // indirect
github.com/ysmood/leakless v0.8.0 // indirect
golang.org/x/crypto v0.5.0 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/mod v0.7.0 // indirect
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 // indirect
golang.org/x/sys v0.5.0 // indirect

201
go.sum
View File

@ -51,28 +51,13 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ=
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw=
github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ=
github.com/aws/aws-sdk-go-v2/service/appconfig v1.4.2/go.mod h1:FZ3HkCe+b10uFZZkFdvf98LHW21k49W8o8J366lqVKY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8=
github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk=
github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/bradfitz/gomemcache v0.0.0-20221031212613-62deef7fc822/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
@ -97,9 +82,7 @@ github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@ -138,20 +121,16 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/fasthttp/router v1.4.16 h1:faWJ9OtaHvAtodreyQLps58M80YFNzphMJtOJzeESXs=
github.com/fasthttp/router v1.4.16/go.mod h1:NFNlTCilbRVkeLc+E5JDkcxUdkpiJGKDL8Zy7Ey2JTI=
github.com/fasthttp/router v1.4.17 h1:Z8fndZotdwcPoYTt8BWwnRBts2UQPnKmOxbb94n0GUc=
github.com/fasthttp/router v1.4.17/go.mod h1:EOMfK/dT1IMzbyPhzw6E2j90owHvY+/BY60bLxOye/8=
github.com/fasthttp/session/v2 v2.4.16 h1:JRvuEqr/+/cNMBkhGZN118FurLh6paUGscwJr26TxAQ=
github.com/fasthttp/session/v2 v2.4.16/go.mod h1:nv8SD6pAx3n3KjJsEt4k1p0vstqclbNcrCwjc1OjuCI=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@ -162,10 +141,10 @@ github.com/fxamacker/cbor/v2 v2.4.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A=
github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-crypt/crypt v0.2.5 h1:QYGV/OkamPz69fME+JbD0wVmPnAL3C1Ooypqb1FHnHk=
github.com/go-crypt/crypt v0.2.5/go.mod h1:VtajXhpCQlYwf4ekvp1I/6bSFi1YKobq0QInA1AFCQQ=
github.com/go-crypt/x v0.1.12 h1:UQvK75MBYGdeY7PdP/YbkUqiGxNzJq3BlO/lTVT6yuU=
github.com/go-crypt/x v0.1.12/go.mod h1:037K8Cyl2IJUzO297LjhDIeYZYxg7K8yzbCco6ZNtV0=
github.com/go-crypt/crypt v0.2.6 h1:OlCSHwqbYnvcemB5N6uL/FlUJJAlQvmIWcJnodIZ1wU=
github.com/go-crypt/crypt v0.2.6/go.mod h1:rnVxiaVafgL1VsN/Pgt+mc2sn2wEozYUr4vS/94rHoI=
github.com/go-crypt/x v0.1.13 h1:kQPfAfudCnpwSL6fS9d637v/QwEwnA6HEkE91yvzIC4=
github.com/go-crypt/x v0.1.13/go.mod h1:vKR4KobuL9RFa+Rts0zItk+u77AFyrvZSD/xQZ4zCpw=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -173,7 +152,6 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-ldap/ldap/v3 v3.4.4 h1:qPjipEpt+qDa6SI/h1fzuGWoRUY+qqQ9sOZq67/PYUs=
github.com/go-ldap/ldap/v3 v3.4.4/go.mod h1:fe1MsuN5eJJ1FeLT/LEBVdWfNWKh459R7aXgXtJC+aI=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -182,24 +160,21 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-rod/rod v0.112.5 h1:2mH97UK8We4D2MfX388WqPjG1lDbxx8lLi5MzfvnEo0=
github.com/go-rod/rod v0.112.5/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0=
github.com/go-rod/rod v0.112.6 h1:zMirUmhsBeshMWyf285BD0UGtGq54HfThLDGSjcP3lU=
github.com/go-rod/rod v0.112.6/go.mod h1:ElViL9ABbcshNQw93+11FrYRH92RRhMKleuILo6+5V0=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-webauthn/revoke v0.1.6 h1:3tv+itza9WpX5tryRQx4GwxCCBrCIiJ8GIkOhxiAmmU=
github.com/go-webauthn/revoke v0.1.6/go.mod h1:TB4wuW4tPlwgF3znujA96F70/YSQXHPPWl7vgY09Iy8=
github.com/go-webauthn/webauthn v0.7.0 h1:Tk2evkiZGtmbgGoYUbNw2BbPyI8e65tfi8HY9mSluWA=
github.com/go-webauthn/webauthn v0.7.0/go.mod h1:FrFAvvr9oP+tXr1WeDpRz/rYJi5GRG0/EVFfpN7YhKA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/go-webauthn/revoke v0.1.9 h1:gSJ1ckA9VaKA2GN4Ukp+kiGTk1/EXtaDb1YE8RknbS0=
github.com/go-webauthn/revoke v0.1.9/go.mod h1:j6WKPnv0HovtEs++paan9g3ar46gm1NarktkXBaPR+w=
github.com/go-webauthn/webauthn v0.7.1 h1:b1/HP1bkqsW+DIO22WyG7BP9dL0rN151VpruH6cxADA=
github.com/go-webauthn/webauthn v0.7.1/go.mod h1:22OJd+TV8oHrjjXmPHtcPR82lR/yR5m5ilGiF8yPFrE=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.4.3 h1:Hxl6lhQFj4AnOX6MLrsCb/+7tCj7DxP7VA+2rDIq5AU=
github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
@ -233,7 +208,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -247,7 +221,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
@ -287,48 +260,16 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hjson/hjson-go/v4 v4.0.0 h1:wlm6IYYqHjOdXH1gHev4VoXCaW20HdQAGCxdOEEg2cs=
github.com/hjson/hjson-go/v4 v4.0.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@ -338,18 +279,14 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgx/v5 v5.2.0 h1:NdPpngX0Y6z6XDFKqmFQaE+bCtkqzvQIOt1wvBlAqs8=
github.com/jackc/pgx/v5 v5.2.0/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
github.com/jandelgado/gcov2lcov v1.0.5 h1:rkBt40h0CVK4oCb8Dps950gvfd1rYvQ8+cWa346lVU0=
github.com/jandelgado/gcov2lcov v1.0.5/go.mod h1:NnSxK6TMlg1oGDBfGelGbjgorT5/L3cchlbtgFYZSss=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@ -362,12 +299,23 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs=
github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs=
github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs=
github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
github.com/knadh/koanf/parsers/yaml v0.1.0 h1:ZZ8/iGfRLvKSaMEECEBPM1HQslrZADk8fP1XFUxVI5w=
github.com/knadh/koanf/parsers/yaml v0.1.0/go.mod h1:cvbUDC7AL23pImuQP0oRw/hPuccrNBS2bps8asS0CwY=
github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU=
github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU=
github.com/knadh/koanf/providers/env v0.1.0 h1:LqKteXqfOWyx5Ab9VfGHmjY9BvRXi+clwyZozgVRiKg=
github.com/knadh/koanf/providers/env v0.1.0/go.mod h1:RE8K9GbACJkeEnkl8L/Qcj8p4ZyPXZIQ191HJi44ZaQ=
github.com/knadh/koanf/providers/posflag v0.1.0 h1:mKJlLrKPcAP7Ootf4pBZWJ6J+4wHYujwipe7Ie3qW6U=
github.com/knadh/koanf/providers/posflag v0.1.0/go.mod h1:SYg03v/t8ISBNrMBRMlojH8OsKowbkXV7giIbBVgbz0=
github.com/knadh/koanf/providers/rawbytes v0.1.0 h1:dpzgu2KO6uf6oCb4aP05KDmKmAmI51k5pe8RYKQ0qME=
github.com/knadh/koanf/providers/rawbytes v0.1.0/go.mod h1:mMTB1/IcJ/yE++A2iEZbY1MLygX7vttU+C+S/YmPu9c=
github.com/knadh/koanf/v2 v2.0.0 h1:XPQ5ilNnwnNaHrfQ1YpTVhUAjcGHnEKA+lRpipQv02Y=
github.com/knadh/koanf/v2 v2.0.0/go.mod h1:ZeiIlIDXTE7w1lMT6UVcNiRAS2/rCeLn/GdLNvY1Dus=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
@ -385,15 +333,7 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
@ -403,23 +343,13 @@ github.com/mattn/goveralls v0.0.11/go.mod h1:gU8SyhNswsJKchEV93xRQxX6X3Ei4PJdQk/
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -431,11 +361,9 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/oleiade/reflections v1.0.1 h1:D1XO3LVEYroYskEsoSiGItp9RUxG6jWnCVvrqH0HHQM=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -459,8 +387,8 @@ github.com/ory/go-convenience v0.1.0/go.mod h1:uEY/a60PL5c12nYz4V5cHY03IBmwIAEm8
github.com/ory/herodot v0.9.13 h1:cN/Z4eOkErl/9W7hDIDLb79IO/bfsH+8yscBjRpB4IU=
github.com/ory/herodot v0.9.13/go.mod h1:IWDs9kSvFQqw/cQ8zi5ksyYvITiUU4dI7glUrhZcJYo=
github.com/ory/viper v1.7.5/go.mod h1:ypOuyJmEUb3oENywQZRgeAMwqgOyDqwboO1tj3DjTaM=
github.com/ory/x v0.0.535 h1:muhBRYkAz52J00yEGw6LtwJDF5HhyxM2w0E0V4w5z+o=
github.com/ory/x v0.0.535/go.mod h1:CQopDsCC9t0tQsddE9UlyRFVEFd2xjKBVcw4nLMMMS0=
github.com/ory/x v0.0.542 h1:3moNM1xRT3GYUSoNet4ZF8bFWE5jY/G526mR9lQVmA0=
github.com/ory/x v0.0.542/go.mod h1:ktXUvx51Ok1gMGr3ysvktanqr+eiB4FXglt4nF4w2Uo=
github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4=
github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
@ -468,13 +396,10 @@ github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4=
github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pborman/uuid v1.2.1 h1:+ZZIw58t/ozdjRaXh/3awHfmWRbzYxJoAdNJxe/3pvw=
github.com/pborman/uuid v1.2.1/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
@ -484,7 +409,6 @@ github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoU
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -492,8 +416,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@ -501,7 +423,6 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
@ -528,7 +449,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@ -537,12 +457,9 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d h1:Q+gqLBOPkFGHyCJxXMRqtUgUbTjI8/Ze8vu8GGyNFwo=
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@ -587,8 +504,9 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
@ -630,9 +548,6 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@ -641,17 +556,13 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@ -660,8 +571,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -685,7 +596,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@ -717,7 +627,6 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -739,7 +648,6 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@ -749,8 +657,8 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -778,18 +686,14 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -798,18 +702,13 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -835,9 +734,7 @@ golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -864,7 +761,6 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -892,7 +788,6 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -917,7 +812,6 @@ golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
@ -928,11 +822,9 @@ golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4=
@ -970,7 +862,6 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@ -1007,16 +898,13 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71 h1:GEgb2jF5zxsFJpJfg9RoDDWm7tiwc/DDSTE2BtLUkXU=
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
@ -1032,7 +920,6 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
@ -1055,7 +942,6 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -1067,7 +953,6 @@ gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
@ -1083,7 +968,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@ -1096,4 +980,3 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@ -536,16 +536,17 @@ const (
const (
cmdFlagNameDirectory = "directory"
cmdFlagNamePathCA = "path.ca"
cmdFlagNameBundle = "bundle"
cmdFlagNamePathCA = "path.ca"
cmdFlagNameBundles = "bundles"
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"
cmdFlagNameFilePrivateKey = "file.private-key"
cmdFlagNameFilePublicKey = "file.public-key"
cmdFlagNameFileCertificate = "file.certificate"
cmdFlagNameFileBundleChain = "file.bundle.chain"
cmdFlagNameFileBundlePrivKeyChain = "file.bundle.priv-chain"
cmdFlagNameFileCAPrivateKey = "file.ca-private-key"
cmdFlagNameFileCACertificate = "file.ca-certificate"
cmdFlagNameFileCSR = "file.csr"
cmdFlagNameExtendedUsage = "extended-usage"
cmdFlagNameSignature = "signature"
@ -776,3 +777,12 @@ Layouts:
const (
fmtLogServerListening = "Server is listening for %s connections on '%s' path '%s'"
)
const (
logFieldService = "service"
logFieldFile = "file"
logFieldOP = "op"
serviceTypeServer = "server"
serviceTypeWatcher = "watcher"
)

View File

@ -365,7 +365,7 @@ func (ctx *CmdCtx) CryptoCertificateGenerateRunE(cmd *cobra.Command, _ []string,
return err
}
b := strings.Builder{}
b := &strings.Builder{}
b.WriteString("Generating Certificate\n\n")
@ -402,9 +402,8 @@ 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 (
dir, privateKeyPath, certificatePath, certificateBundlePath string
dir, privateKeyPath, certificatePath string
bundle bool
certificate []byte
)
@ -412,10 +411,6 @@ func (ctx *CmdCtx) CryptoCertificateGenerateRunE(cmd *cobra.Command, _ []string,
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", certificatePath))
@ -432,10 +427,8 @@ func (ctx *CmdCtx) CryptoCertificateGenerateRunE(cmd *cobra.Command, _ []string,
return err
}
if bundle {
b.WriteString(fmt.Sprintf("\tCertificate (bundle): %s\n", certificateBundlePath))
if err = utils.WriteCertificateBytesToPEM(certificateBundlePath, false, certificate, caCertificate.Raw); err != nil {
if cmd.Flags().Changed(cmdFlagNameBundles) {
if err = cryptoGenerateCertificateBundlesFromCmd(cmd, b, dir, caCertificate, certificate, privateKey); err != nil {
return err
}
}

View File

@ -7,6 +7,7 @@ import (
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"net"
@ -43,8 +44,9 @@ 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().String(cmdFlagNameFileBundleChain, "public.chain.pem", fmt.Sprintf("name of the file to export the certificate chain PEM bundle to when the --%s flag includes 'chain'", cmdFlagNameBundles))
cmd.Flags().String(cmdFlagNameFileBundlePrivKeyChain, "private.chain.pem", fmt.Sprintf("name of the file to export the certificate chain and private key PEM bundle to when the --%s flag includes 'priv-chain'", cmdFlagNameBundles))
cmd.Flags().StringSlice(cmdFlagNameBundles, nil, "enables generating bundles options are 'chain' and 'privkey-chain'")
cmd.Flags().StringSlice(cmdFlagNameExtendedUsage, nil, "specify the extended usage types of the certificate")
@ -170,26 +172,60 @@ 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
func cryptoGenerateCertificateBundlesFromCmd(cmd *cobra.Command, b *strings.Builder, dir string, ca *x509.Certificate, certificate []byte, privkey any) (err error) {
var bundles []string
if bundles, err = cmd.Flags().GetStringSlice(cmdFlagNameBundles); err != nil {
return err
}
if !bundle {
return bundle, bundlePath, err
blocks := []*pem.Block{
{Type: utils.BlockTypeCertificate, Bytes: certificate},
}
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 ca != nil {
blocks = append(blocks, &pem.Block{Type: utils.BlockTypeCertificate, Bytes: ca.Raw})
}
if bundlePath, err = cmd.Flags().GetString(cmdFlagNameFileCertificateBundle); err != nil {
return false, "", err
var name string
if utils.IsStringInSliceFold("chain", bundles) {
if name, err = cmd.Flags().GetString(cmdFlagNameFileBundleChain); err != nil {
return err
}
pathPEM := filepath.Join(dir, name)
b.WriteString(fmt.Sprintf("\tCertificate (chain): %s\n", pathPEM))
if err = utils.WritePEM(pathPEM, blocks...); err != nil {
return err
}
}
bundlePath = filepath.Join(dir, bundlePath)
if utils.IsStringInSliceFold("priv-chain", bundles) {
if name, err = cmd.Flags().GetString(cmdFlagNameFileBundlePrivKeyChain); err != nil {
return err
}
return bundle, bundlePath, err
var block *pem.Block
if block, err = utils.PEMBlockFromX509Key(privkey, false); err != nil {
return err
}
blocks = append([]*pem.Block{block}, blocks...)
pathPEM := filepath.Join(dir, name)
b.WriteString(fmt.Sprintf("\tCertificate (priv-chain): %s\n", pathPEM))
if err = utils.WritePEM(pathPEM, blocks...); err != nil {
return err
}
}
return nil
}
func cryptoGetCAFromCmd(cmd *cobra.Command) (privateKey any, cert *x509.Certificate, err error) {

View File

@ -10,6 +10,7 @@ import (
"strings"
"sync"
"syscall"
"time"
"github.com/fsnotify/fsnotify"
"github.com/sirupsen/logrus"
@ -23,11 +24,12 @@ import (
// NewServerService creates a new ServerService with the appropriate logger etc.
func NewServerService(name string, server *fasthttp.Server, listener net.Listener, paths []string, isTLS bool, log *logrus.Logger) (service *ServerService) {
return &ServerService{
name: name,
server: server,
listener: listener,
paths: paths,
isTLS: isTLS,
log: log.WithFields(map[string]any{"service": "server", "server": name}),
log: log.WithFields(map[string]any{logFieldService: serviceTypeServer, serviceTypeServer: name}),
}
}
@ -53,10 +55,11 @@ func NewFileWatcherService(name, path string, reload ProviderReload, log *logrus
return nil, err
}
entry := log.WithFields(map[string]any{"service": "watcher", "watcher": name})
entry := log.WithFields(map[string]any{logFieldService: serviceTypeWatcher, serviceTypeWatcher: name})
if info.IsDir() {
service = &FileWatcherService{
name: name,
watcher: watcher,
reload: reload,
log: entry,
@ -64,6 +67,7 @@ func NewFileWatcherService(name, path string, reload ProviderReload, log *logrus
}
} else {
service = &FileWatcherService{
name: name,
watcher: watcher,
reload: reload,
log: entry,
@ -86,12 +90,25 @@ type ProviderReload interface {
// Service represents the required methods to support handling a service.
type Service interface {
// ServiceType returns the type name for the Service.
ServiceType() string
// ServiceName returns the individual name for the Service.
ServiceName() string
// Run performs the running operations for the Service.
Run() (err error)
// Shutdown perform the shutdown cleanup and termination operations for the Service.
Shutdown()
// Log returns the logger configured for the service.
Log() *logrus.Entry
}
// ServerService is a Service which runs a webserver.
type ServerService struct {
name string
server *fasthttp.Server
paths []string
isTLS bool
@ -99,6 +116,16 @@ type ServerService struct {
log *logrus.Entry
}
// ServiceType returns the service type for this service, which is always 'server'.
func (service *ServerService) ServiceType() string {
return serviceTypeServer
}
// ServiceName returns the individual name for this service.
func (service *ServerService) ServiceName() string {
return service.name
}
// Run the ServerService.
func (service *ServerService) Run() (err error) {
defer func() {
@ -120,13 +147,24 @@ func (service *ServerService) Run() (err error) {
// Shutdown the ServerService.
func (service *ServerService) Shutdown() {
if err := service.server.Shutdown(); err != nil {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()
if err := service.server.ShutdownWithContext(ctx); err != nil {
service.log.WithError(err).Error("Error occurred during shutdown")
}
}
// Log returns the *logrus.Entry of the ServerService.
func (service *ServerService) Log() *logrus.Entry {
return service.log
}
// FileWatcherService is a Service that watches files for changes.
type FileWatcherService struct {
name string
watcher *fsnotify.Watcher
reload ProviderReload
@ -135,6 +173,16 @@ type FileWatcherService struct {
directory string
}
// ServiceType returns the service type for this service, which is always 'watcher'.
func (service *FileWatcherService) ServiceType() string {
return serviceTypeWatcher
}
// ServiceName returns the individual name for this service.
func (service *FileWatcherService) ServiceName() string {
return service.name
}
// Run the FileWatcherService.
func (service *FileWatcherService) Run() (err error) {
defer func() {
@ -143,7 +191,7 @@ func (service *FileWatcherService) Run() (err error) {
}
}()
service.log.WithField("file", filepath.Join(service.directory, service.file)).Info("Watching for file changes to the file")
service.log.WithField(logFieldFile, filepath.Join(service.directory, service.file)).Info("Watching file for changes")
for {
select {
@ -152,34 +200,36 @@ func (service *FileWatcherService) Run() (err error) {
return nil
}
log := service.log.WithFields(map[string]any{logFieldFile: event.Name, logFieldOP: event.Op})
if service.file != "" && service.file != filepath.Base(event.Name) {
service.log.WithFields(map[string]any{"file": event.Name, "op": event.Op}).Tracef("File modification detected to irrelevant file")
log.Trace("File modification detected to irrelevant file")
break
}
switch {
case event.Op&fsnotify.Write == fsnotify.Write, event.Op&fsnotify.Create == fsnotify.Create:
service.log.WithFields(map[string]any{"file": event.Name, "op": event.Op}).Debug("File modification was detected")
log.Debug("File modification was detected")
var reloaded bool
switch reloaded, err = service.reload.Reload(); {
case err != nil:
service.log.WithFields(map[string]any{"file": event.Name, "op": event.Op}).WithError(err).Error("Error occurred during reload")
log.WithError(err).Error("Error occurred during reload")
case reloaded:
service.log.WithField("file", event.Name).Info("Reloaded successfully")
log.Info("Reloaded successfully")
default:
service.log.WithField("file", event.Name).Debug("Reload of was triggered but it was skipped")
log.Debug("Reload was triggered but it was skipped")
}
case event.Op&fsnotify.Remove == fsnotify.Remove:
service.log.WithFields(map[string]any{"file": event.Name, "op": event.Op}).Debug("File remove was detected")
log.Debug("File remove was detected")
}
case err, ok := <-service.watcher.Errors:
if !ok {
return nil
}
service.log.WithError(err).Errorf("Error while watching files")
service.log.WithError(err).Error("Error while watching file for changes")
}
}
}
@ -191,6 +241,11 @@ func (service *FileWatcherService) Shutdown() {
}
}
// Log returns the *logrus.Entry of the FileWatcherService.
func (service *FileWatcherService) Log() *logrus.Entry {
return service.log
}
func svcSvrMainFunc(ctx *CmdCtx) (service Service) {
switch svr, listener, paths, isTLS, err := server.CreateDefaultServer(ctx.config, ctx.providers); {
case err != nil:
@ -267,34 +322,35 @@ func servicesRun(ctx *CmdCtx) {
}
}
ctx.log.Info("Startup Complete")
ctx.log.Info("Startup complete")
select {
case s := <-quit:
switch s {
case syscall.SIGINT:
ctx.log.WithField("signal", "SIGINT").Debugf("Shutdown started due to signal")
case syscall.SIGTERM:
ctx.log.WithField("signal", "SIGTERM").Debugf("Shutdown started due to signal")
}
ctx.log.WithField("signal", s.String()).Debug("Shutdown initiated due to process signal")
case <-cctx.Done():
ctx.log.Debugf("Shutdown started due to context completion")
ctx.log.Debug("Shutdown initiated due to context completion")
}
cancel()
ctx.log.Infof("Shutting down")
ctx.log.Info("Shutdown initiated")
wgShutdown := &sync.WaitGroup{}
ctx.log.Tracef("Shutdown of %d services is required", len(services))
for _, service := range services {
go func() {
wgShutdown.Add(1)
go func(service Service) {
service.Log().Trace("Shutdown of service initiated")
service.Shutdown()
wgShutdown.Done()
}()
wgShutdown.Add(1)
service.Log().Trace("Shutdown of service complete")
}(service)
}
wgShutdown.Wait()
@ -306,6 +362,8 @@ func servicesRun(ctx *CmdCtx) {
}
if err = group.Wait(); err != nil {
ctx.log.WithError(err).Errorf("Error occurred waiting for shutdown")
ctx.log.WithError(err).Error("Error occurred waiting for shutdown")
}
ctx.log.Info("Shutdown complete")
}

View File

@ -4,8 +4,8 @@ import (
"fmt"
"strings"
"github.com/knadh/koanf"
"github.com/knadh/koanf/providers/confmap"
"github.com/knadh/koanf/v2"
"github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/utils"

View File

@ -3,9 +3,9 @@ package configuration
import (
"testing"
"github.com/knadh/koanf"
"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/rawbytes"
"github.com/knadh/koanf/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

View File

@ -3,7 +3,7 @@ package configuration
import (
"fmt"
"github.com/knadh/koanf"
"github.com/knadh/koanf/v2"
"github.com/mitchellh/mapstructure"
"github.com/authelia/authelia/v4/internal/configuration/schema"

View File

@ -6,11 +6,11 @@ import (
"os"
"path/filepath"
"github.com/knadh/koanf"
"github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/confmap"
"github.com/knadh/koanf/providers/env"
"github.com/knadh/koanf/providers/posflag"
"github.com/knadh/koanf/v2"
"github.com/spf13/pflag"
"github.com/authelia/authelia/v4/internal/configuration/schema"

View File

@ -1,7 +1,7 @@
package configuration
import (
"github.com/knadh/koanf"
"github.com/knadh/koanf/v2"
"github.com/spf13/pflag"
"github.com/authelia/authelia/v4/internal/configuration/schema"

View File

@ -112,7 +112,7 @@ func (authz *Authz) getAutheliaURL(ctx *middlewares.AutheliaCtx, provider *sessi
return nil, err
}
if autheliaURL != nil {
if autheliaURL != nil || authz.legacy {
return autheliaURL, nil
}

View File

@ -139,7 +139,7 @@ func (s *LegacyAuthzSuite) TestShouldHandleAllMethodsOverrideAutheliaURLDeny() {
}
}
func (s *LegacyAuthzSuite) TestShouldHandleAllMethodsMissingAutheliaURLDeny() {
func (s *LegacyAuthzSuite) TestShouldHandleAllMethodsMissingAutheliaURLBypassStatus200() {
for _, method := range testRequestMethods {
s.T().Run(fmt.Sprintf("Method%s", method), func(t *testing.T) {
for _, targetURI := range []*url.URL{
@ -163,6 +163,38 @@ func (s *LegacyAuthzSuite) TestShouldHandleAllMethodsMissingAutheliaURLDeny() {
authz.Handler(mock.Ctx)
assert.Equal(t, fasthttp.StatusOK, mock.Ctx.Response.StatusCode())
assert.Equal(t, "", string(mock.Ctx.Response.Header.Peek(fasthttp.HeaderLocation)))
})
}
})
}
}
func (s *LegacyAuthzSuite) TestShouldHandleAllMethodsMissingAutheliaURLOneFactorStatus401() {
for _, method := range testRequestMethods {
s.T().Run(fmt.Sprintf("Method%s", method), func(t *testing.T) {
for _, targetURI := range []*url.URL{
s.RequireParseRequestURI("https://one-factor.example.com"),
s.RequireParseRequestURI("https://one-factor.example.com/subpath"),
s.RequireParseRequestURI("https://one-factor.example2.com"),
s.RequireParseRequestURI("https://one-factor.example2.com/subpath"),
} {
t.Run(targetURI.String(), func(t *testing.T) {
authz := s.Builder().Build()
mock := mocks.NewMockAutheliaCtx(t)
defer mock.Close()
mock.Ctx.Request.Header.Set("X-Forwarded-Method", method)
mock.Ctx.Request.Header.Set(fasthttp.HeaderXForwardedProto, targetURI.Scheme)
mock.Ctx.Request.Header.Set(fasthttp.HeaderXForwardedHost, targetURI.Host)
mock.Ctx.Request.Header.Set("X-Forwarded-Uri", targetURI.Path)
mock.Ctx.Request.Header.Set(fasthttp.HeaderAccept, "text/html; charset=utf-8")
authz.Handler(mock.Ctx)
assert.Equal(t, fasthttp.StatusUnauthorized, mock.Ctx.Response.StatusCode())
assert.Equal(t, "", string(mock.Ctx.Response.Header.Peek(fasthttp.HeaderLocation)))
})
@ -171,6 +203,47 @@ func (s *LegacyAuthzSuite) TestShouldHandleAllMethodsMissingAutheliaURLDeny() {
}
}
func (s *LegacyAuthzSuite) TestShouldHandleAllMethodsRDAutheliaURLOneFactorStatus302Or303() {
for _, method := range testRequestMethods {
s.T().Run(fmt.Sprintf("Method%s", method), func(t *testing.T) {
for _, targetURI := range []*url.URL{
s.RequireParseRequestURI("https://one-factor.example.com/"),
s.RequireParseRequestURI("https://one-factor.example.com/subpath"),
} {
t.Run(targetURI.String(), func(t *testing.T) {
authz := s.Builder().Build()
mock := mocks.NewMockAutheliaCtx(t)
defer mock.Close()
mock.Ctx.Request.Header.Set("X-Forwarded-Method", method)
mock.Ctx.Request.Header.Set(fasthttp.HeaderXForwardedProto, targetURI.Scheme)
mock.Ctx.Request.Header.Set(fasthttp.HeaderXForwardedHost, targetURI.Host)
mock.Ctx.Request.Header.Set("X-Forwarded-Uri", targetURI.Path)
mock.Ctx.Request.Header.Set(fasthttp.HeaderAccept, "text/html; charset=utf-8")
mock.Ctx.Request.SetRequestURI("/api/verify?rd=https%3A%2F%2Fauth.example.com")
authz.Handler(mock.Ctx)
switch method {
case fasthttp.MethodGet, fasthttp.MethodOptions:
assert.Equal(t, fasthttp.StatusFound, mock.Ctx.Response.StatusCode())
default:
assert.Equal(t, fasthttp.StatusSeeOther, mock.Ctx.Response.StatusCode())
}
query := &url.Values{}
query.Set("rd", targetURI.String())
query.Set("rm", method)
assert.Equal(t, fmt.Sprintf("https://auth.example.com/?%s", query.Encode()), string(mock.Ctx.Response.Header.Peek(fasthttp.HeaderLocation)))
})
}
})
}
}
func (s *LegacyAuthzSuite) TestShouldHandleAllMethodsXHRDeny() {
for _, method := range testRequestMethods {
s.T().Run(fmt.Sprintf("Method%s", method), func(t *testing.T) {

View File

@ -1,8 +1,6 @@
package handlers
import (
"net/url"
"github.com/valyala/fasthttp"
"github.com/authelia/authelia/v4/internal/middlewares"
@ -11,20 +9,11 @@ import (
// OpenIDConnectConfigurationWellKnownGET handles requests to a .well-known endpoint (RFC5785) which returns the
// OpenID Connect Discovery 1.0 metadata.
//
// https://datatracker.ietf.org/doc/html/rfc5785
// RFC5785: Defining Well-Known URIs (https://datatracker.ietf.org/doc/html/rfc5785)
//
// https://openid.net/specs/openid-connect-discovery-1_0.html
// OpenID Connect Discovery 1.0 (https://openid.net/specs/openid-connect-discovery-1_0.html)
func OpenIDConnectConfigurationWellKnownGET(ctx *middlewares.AutheliaCtx) {
var (
issuer *url.URL
err error
)
issuer = ctx.RootURL()
wellKnown := ctx.Providers.OpenIDConnect.GetOpenIDConnectWellKnownConfiguration(issuer.String())
if err = ctx.ReplyJSON(wellKnown, fasthttp.StatusOK); err != nil {
if err := ctx.ReplyJSON(ctx.Providers.OpenIDConnect.GetOpenIDConnectWellKnownConfiguration(ctx.RootURL().String()), fasthttp.StatusOK); err != nil {
ctx.Logger.Errorf("Error occurred in JSON encode: %+v", err)
// TODO: Determine if this is the appropriate error code here.
@ -37,20 +26,11 @@ func OpenIDConnectConfigurationWellKnownGET(ctx *middlewares.AutheliaCtx) {
// OAuthAuthorizationServerWellKnownGET handles requests to a .well-known endpoint (RFC5785) which returns the
// OAuth 2.0 Authorization Server Metadata (RFC8414).
//
// https://datatracker.ietf.org/doc/html/rfc5785
// RFC5785: Defining Well-Known URIs (https://datatracker.ietf.org/doc/html/rfc5785)
//
// https://datatracker.ietf.org/doc/html/rfc8414
// RFC8414: OAuth 2.0 Authorization Server Metadata (https://datatracker.ietf.org/doc/html/rfc8414)
func OAuthAuthorizationServerWellKnownGET(ctx *middlewares.AutheliaCtx) {
var (
issuer *url.URL
err error
)
issuer = ctx.RootURL()
wellKnown := ctx.Providers.OpenIDConnect.GetOAuth2WellKnownConfiguration(issuer.String())
if err = ctx.ReplyJSON(wellKnown, fasthttp.StatusOK); err != nil {
if err := ctx.ReplyJSON(ctx.Providers.OpenIDConnect.GetOAuth2WellKnownConfiguration(ctx.RootURL().String()), fasthttp.StatusOK); err != nil {
ctx.Logger.Errorf("Error occurred in JSON encode: %+v", err)
// TODO: Determine if this is the appropriate error code here.

View File

@ -75,7 +75,7 @@ func TestWebauthnGetUser(t *testing.T) {
descriptors := user.WebAuthnCredentialDescriptors()
assert.Equal(t, "fido-u2f", descriptors[0].AttestationType)
assert.Equal(t, []byte("abc123"), descriptors[0].CredentialID)
assert.Equal(t, "abc123", string(descriptors[0].CredentialID))
assert.Equal(t, protocol.PublicKeyCredentialType, descriptors[0].Type)
assert.Len(t, descriptors[0].Transport, 0)
@ -91,7 +91,7 @@ func TestWebauthnGetUser(t *testing.T) {
assert.False(t, user.Devices[1].CloneWarning)
assert.Equal(t, "packed", descriptors[1].AttestationType)
assert.Equal(t, []byte("123abc"), descriptors[1].CredentialID)
assert.Equal(t, "123abc", string(descriptors[1].CredentialID))
assert.Equal(t, protocol.PublicKeyCredentialType, descriptors[1].Type)
assert.Len(t, descriptors[1].Transport, 2)

View File

@ -50,7 +50,7 @@ func InitializeLogger(config schema.LogConfiguration, log bool) error {
}
if config.FilePath != "" {
filePath := strings.ReplaceAll(config.FilePath, "%d", time.Now().Format("2006-02-01T150405Z"))
filePath := strings.ReplaceAll(config.FilePath, "%d", time.Now().Format(time.RFC3339))
f, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)

View File

@ -11,6 +11,7 @@ import (
"net/http"
"path"
"path/filepath"
"strconv"
"strings"
"github.com/valyala/fasthttp"
@ -64,7 +65,15 @@ func newPublicHTMLEmbeddedHandler() fasthttp.RequestHandler {
}
ctx.SetContentType(contentType)
ctx.SetBody(data)
switch {
case ctx.IsHead():
ctx.Response.ResetBody()
ctx.Response.SkipBody = true
ctx.Response.Header.Set(fasthttp.HeaderContentLength, strconv.Itoa(len(data)))
default:
ctx.SetBody(data)
}
}
}
@ -182,7 +191,14 @@ func newLocalesEmbeddedHandler() (handler fasthttp.RequestHandler) {
middlewares.SetContentTypeApplicationJSON(ctx)
ctx.SetBody(data)
switch {
case ctx.IsHead():
ctx.Response.ResetBody()
ctx.Response.SkipBody = true
ctx.Response.Header.Set(fasthttp.HeaderContentLength, strconv.Itoa(len(data)))
default:
ctx.SetBody(data)
}
}
}

View File

@ -1,6 +1,7 @@
package server
import (
"fmt"
"net"
"os"
"path"
@ -77,10 +78,10 @@ func handleError() func(ctx *fasthttp.RequestCtx, err error) {
func handleNotFound(next fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(ctx *fasthttp.RequestCtx) {
path := strings.ToLower(string(ctx.Path()))
uri := strings.ToLower(string(ctx.Path()))
for i := 0; i < len(dirsHTTPServer); i++ {
if path == dirsHTTPServer[i].name || strings.HasPrefix(path, dirsHTTPServer[i].prefix) {
if uri == dirsHTTPServer[i].name || strings.HasPrefix(uri, dirsHTTPServer[i].prefix) {
handlers.SetStatusCodeResponse(ctx, fasthttp.StatusNotFound)
return
@ -91,6 +92,13 @@ func handleNotFound(next fasthttp.RequestHandler) fasthttp.RequestHandler {
}
}
func handleMethodNotAllowed(ctx *fasthttp.RequestCtx) {
middlewares.SetContentTypeTextPlain(ctx)
ctx.SetStatusCode(fasthttp.StatusMethodNotAllowed)
ctx.SetBodyString(fmt.Sprintf("%d %s", fasthttp.StatusMethodNotAllowed, fasthttp.StatusMessage(fasthttp.StatusMethodNotAllowed)))
}
//nolint:gocyclo
func handleRouter(config *schema.Configuration, providers middlewares.Providers) fasthttp.RequestHandler {
log := logging.Logger()
@ -115,29 +123,45 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers)
r := router.New()
// Static Assets.
r.HEAD("/", bridge(serveIndexHandler))
r.GET("/", bridge(serveIndexHandler))
for _, f := range filesRoot {
r.HEAD("/"+f, handlerPublicHTML)
r.GET("/"+f, handlerPublicHTML)
}
r.HEAD("/favicon.ico", middlewares.AssetOverride(config.Server.AssetPath, 0, handlerPublicHTML))
r.GET("/favicon.ico", middlewares.AssetOverride(config.Server.AssetPath, 0, handlerPublicHTML))
r.HEAD("/static/media/logo.png", middlewares.AssetOverride(config.Server.AssetPath, 2, handlerPublicHTML))
r.GET("/static/media/logo.png", middlewares.AssetOverride(config.Server.AssetPath, 2, handlerPublicHTML))
r.HEAD("/static/{filepath:*}", handlerPublicHTML)
r.GET("/static/{filepath:*}", handlerPublicHTML)
// Locales.
r.HEAD("/locales/{language:[a-z]{1,3}}-{variant:[a-zA-Z0-9-]+}/{namespace:[a-z]+}.json", middlewares.AssetOverride(config.Server.AssetPath, 0, handlerLocales))
r.GET("/locales/{language:[a-z]{1,3}}-{variant:[a-zA-Z0-9-]+}/{namespace:[a-z]+}.json", middlewares.AssetOverride(config.Server.AssetPath, 0, handlerLocales))
r.HEAD("/locales/{language:[a-z]{1,3}}/{namespace:[a-z]+}.json", middlewares.AssetOverride(config.Server.AssetPath, 0, handlerLocales))
r.GET("/locales/{language:[a-z]{1,3}}/{namespace:[a-z]+}.json", middlewares.AssetOverride(config.Server.AssetPath, 0, handlerLocales))
// Swagger.
r.HEAD("/api/", bridge(serveOpenAPIHandler))
r.GET("/api/", bridge(serveOpenAPIHandler))
r.OPTIONS("/api/", policyCORSPublicGET.HandleOPTIONS)
r.HEAD("/api/index.html", bridge(serveOpenAPIHandler))
r.GET("/api/index.html", bridge(serveOpenAPIHandler))
r.OPTIONS("/api/index.html", policyCORSPublicGET.HandleOPTIONS)
r.HEAD("/api/openapi.yml", policyCORSPublicGET.Middleware(bridge(serveOpenAPISpecHandler)))
r.GET("/api/openapi.yml", policyCORSPublicGET.Middleware(bridge(serveOpenAPISpecHandler)))
r.OPTIONS("/api/openapi.yml", policyCORSPublicGET.HandleOPTIONS)
for _, file := range filesSwagger {
r.HEAD("/api/"+file, handlerPublicHTML)
r.GET("/api/"+file, handlerPublicHTML)
}
@ -150,7 +174,9 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers)
WithPostMiddlewares(middlewares.Require1FA).
Build()
r.HEAD("/api/health", middlewareAPI(handlers.HealthGET))
r.GET("/api/health", middlewareAPI(handlers.HealthGET))
r.GET("/api/state", middlewareAPI(handlers.StateGET))
r.GET("/api/configuration", middleware1FA(handlers.ConfigurationGET))
@ -356,7 +382,7 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers)
}
r.HandleMethodNotAllowed = true
r.MethodNotAllowed = handlers.Status(fasthttp.StatusMethodNotAllowed)
r.MethodNotAllowed = handleMethodNotAllowed
r.NotFound = handleNotFound(bridge(serveIndexHandler))
handler := middlewares.LogRequest(r.Handler)

View File

@ -5,5 +5,7 @@
"RememberMe":"{{ .RememberMe }}",
"ResetPassword":"{{ .ResetPassword }}",
"ResetPasswordCustomURL":"{{ .ResetPasswordCustomURL }}",
"PrivacyPolicyURL":"{{ .PrivacyPolicyURL }}",
"PrivacyPolicyAccept":"{{ .PrivacyPolicyAccept }}",
"Theme":"{{ .Theme }}"
}

View File

@ -6,6 +6,7 @@ import (
"encoding/hex"
"fmt"
"os"
"path"
"path/filepath"
"strconv"
"strings"
@ -25,7 +26,7 @@ import (
// and generate a nonce to support a restrictive CSP while using material-ui.
func ServeTemplatedFile(t templates.Template, opts *TemplatedFileOptions) middlewares.RequestHandler {
isDevEnvironment := os.Getenv(environment) == dev
ext := filepath.Ext(t.Name())
ext := path.Ext(t.Name())
return func(ctx *middlewares.AutheliaCtx) {
var err error
@ -67,18 +68,34 @@ func ServeTemplatedFile(t templates.Template, opts *TemplatedFileOptions) middle
rememberMe = strconv.FormatBool(!provider.Config.DisableRememberMe)
}
if err = t.Execute(ctx.Response.BodyWriter(), opts.CommonData(ctx.BasePath(), ctx.RootURLSlash().String(), nonce, logoOverride, rememberMe)); err != nil {
ctx.RequestCtx.Error("an error occurred", 503)
data := &bytes.Buffer{}
if err = t.Execute(data, opts.CommonData(ctx.BasePath(), ctx.RootURLSlash().String(), nonce, logoOverride, rememberMe)); err != nil {
ctx.RequestCtx.Error("an error occurred", fasthttp.StatusServiceUnavailable)
ctx.Logger.WithError(err).Errorf("Error occcurred rendering template")
return
}
switch {
case ctx.IsHead():
ctx.Response.ResetBody()
ctx.Response.SkipBody = true
ctx.Response.Header.Set(fasthttp.HeaderContentLength, strconv.Itoa(data.Len()))
default:
if _, err = data.WriteTo(ctx.Response.BodyWriter()); err != nil {
ctx.RequestCtx.Error("an error occurred", fasthttp.StatusServiceUnavailable)
ctx.Logger.WithError(err).Errorf("Error occcurred writing body")
return
}
}
}
}
// ServeTemplatedOpenAPI serves templated OpenAPI related files.
func ServeTemplatedOpenAPI(t templates.Template, opts *TemplatedFileOptions) middlewares.RequestHandler {
ext := filepath.Ext(t.Name())
ext := path.Ext(t.Name())
spec := ext == extYML
@ -103,12 +120,28 @@ func ServeTemplatedOpenAPI(t templates.Template, opts *TemplatedFileOptions) mid
var err error
if err = t.Execute(ctx.Response.BodyWriter(), opts.OpenAPIData(ctx.BasePath(), ctx.RootURLSlash().String(), nonce)); err != nil {
ctx.RequestCtx.Error("an error occurred", 503)
data := &bytes.Buffer{}
if err = t.Execute(data, opts.OpenAPIData(ctx.BasePath(), ctx.RootURLSlash().String(), nonce)); err != nil {
ctx.RequestCtx.Error("an error occurred", fasthttp.StatusServiceUnavailable)
ctx.Logger.WithError(err).Errorf("Error occcurred rendering template")
return
}
switch {
case ctx.IsHead():
ctx.Response.ResetBody()
ctx.Response.SkipBody = true
ctx.Response.Header.Set(fasthttp.HeaderContentLength, strconv.Itoa(data.Len()))
default:
if _, err = data.WriteTo(ctx.Response.BodyWriter()); err != nil {
ctx.RequestCtx.Error("an error occurred", fasthttp.StatusServiceUnavailable)
ctx.Logger.WithError(err).Errorf("Error occcurred writing body")
return
}
}
}
}
@ -139,6 +172,11 @@ func ETagRootURL(next middlewares.RequestHandler) middlewares.RequestHandler {
next(ctx)
if ctx.Response.SkipBody || ctx.Response.StatusCode() != fasthttp.StatusOK {
// Skip generating the ETag as the response body should be empty.
return
}
mu.Lock()
h.Write(ctx.Response.Body())

View File

@ -3,7 +3,7 @@ version: '3'
services:
authelia-backend:
environment:
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_CERTIFICATE_CHAIN_FILE: /pki/public.oidc.bundle.crt
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_CERTIFICATE_CHAIN_FILE: /pki/public.oidc.chain.pem
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE: /pki/private.oidc.pem
volumes:
- './OIDC/configuration.yml:/config/configuration.yml:ro'

View File

@ -3,7 +3,7 @@ version: '3'
services:
authelia-backend:
environment:
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_CERTIFICATE_CHAIN_FILE: /pki/public.oidc.bundle.crt
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_CERTIFICATE_CHAIN_FILE: /pki/public.oidc.chain.pem
AUTHELIA_IDENTITY_PROVIDERS_OIDC_ISSUER_PRIVATE_KEY_FILE: /pki/private.oidc.pem
volumes:
- './OIDCTraefik/configuration.yml:/config/configuration.yml:ro'

View File

@ -2,6 +2,6 @@
# go run ./cmd/authelia crypto certificate rsa generate --directory ./internal/suites/common/pki/ca -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
# cp ./internal/suites/common/pki/ca/ca.public.crt ./internal/suites/common/pki/ca.public.crt
go run ./cmd/authelia crypto certificate rsa generate --directory ./internal/suites/common/pki --path.ca ./internal/suites/common/pki/ca -n '*.example.com' --sans '*.example.com,example.com,*.example1.com,example1.com,*.example2.com,example2.com,*.example3.com,example3.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/ca --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
go run ./cmd/authelia crypto certificate rsa generate --directory ./internal/suites/common/pki --path.ca ./internal/suites/common/pki/ca --file.certificate public.oidc.crt --file.certificate-bundle public.oidc.bundle.crt --file.private-key private.oidc.pem -n 'login.example.com' --sans 'login.example.com,login.example1.com,login.example2.com,login.example3,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/ca --bundles 'chain,priv-chain' -n '*.example.com' --sans '*.example.com,example.com,*.example1.com,example1.com,*.example2.com,example2.com,*.example3.com,example3.com' --not-before 'Jan 1 00:00:00 2000' --not-after 'Jan 1 00:00:00 2100' -o 'Authelia' --organizational-unit 'Development'
go run ./cmd/authelia crypto certificate rsa generate --directory ./internal/suites/common/pki --path.ca ./internal/suites/common/pki/ca --bundles 'chain,priv-chain' --file.certificate public.backend.crt --file.private-key private.backend.pem --file.bundle.chain public.backend.chain.pem --file.bundle.priv-chain private.backend.chain.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'
go run ./cmd/authelia crypto certificate rsa generate --directory ./internal/suites/common/pki --path.ca ./internal/suites/common/pki/ca --bundles 'chain,priv-chain' --file.certificate public.oidc.crt --file.private-key private.oidc.pem --file.bundle.chain public.oidc.chain.pem --file.bundle.priv-chain private.oidc.chain.pem -n 'login.example.com' --sans 'login.example.com,login.example1.com,login.example2.com,login.example3,com' --not-before 'Jan 1 00:00:00 2000' --not-after 'Jan 1 00:00:00 2100' -o 'Authelia' --organizational-unit 'Development'

View File

@ -0,0 +1,70 @@
-----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-----
-----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-----

View File

@ -0,0 +1,72 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA6iddZfII40v7nj01EmJNkzWvTZJm2WskbPi+hFlXquYeltt6
JZsrttfatYYcraAM5weD6irYzNIBEuQQQ7mtjKlZQmgFtrTcA4xGMpjjQhOI0LJs
LhGMGYDw5ZFRTHuHjhAAUsBQi8gEEwCoqt2sC/sh1TlirLiGqPCA6lQsFeoYmUDs
4OC6bBMKn0ceS1jRODB845kpv37NQN3fEqR6z3ErmCoSVUNL9IGwfM2MeeDg2X1W
0eJ3I4ojLpdG7nYhnwO3guV0XxHWqQQ7yLEjEiffiv8GFPqigPf+qVJDhBzBdYmQ
5tGfRZjafNXmI987Nlho08eGZ12E6sJJdQjjmQIDAQABAoIBAQDm/7rGbgaSpk0v
CNcosc4yIk41Su8oIukmkCbzzmgMc0VOMmvIWdLAaSac2hfEuhbAfMuI4ohLWAoz
Jsdc6Prrv84NEy4/1yEOZv6BwA7DCx54NO1AbZM3PdtpvvjjaSKL5gFLoepUXBiY
3peHKXUnxLLV9e0A1HIUjF/BzRRI8GwBjgUgljJQXCdBk7bHKkep8U4SGScQI6bK
fUcwt4dL7nLObSqRNQYSZJYT8CXw1XbfK51mZFCsPIQ8TE+M6B1ato1umYFk3gr9
CaEVeTpYc9R4HDmmXJT7r5kzQQ/Yciqksgv4pVyAsKGclVyhYN57pCyj82xnHvAL
NJaZ2yt5AoGBAPGaQXLOeGildhdEsDBF7rNGecJOCZEB4f2WTiun8rUP/75fIbn3
NW5kBU2oicMyZSrj9EZ4nho07CoPFl5GCqgK4iwwqzdgPi50oxavW6YMS2OBgrmS
2EXVyHqSwuAEJBn5kYYdd7uCLcw54lrXkokHMbXJC/dzbfUDaGVWMSXDAoGBAPgb
eZADZUZi0KXZ1l47IiMfVO2d+2Ly/gGaeDC8dsZ4eSsoi5F6cheZAxqAjSQhg30M
1NbZJ0GV2PHTjK1a4q4D9vBjSA6cpfbsgutXPHLvbQMOu68hVJxyqCzpW2M9kd5D
1/uqkHy4Wcp6MuprR+/tXWMtcxr50Hmie/3M349zAoGBAMdJ8ZCs5T+UtItO+nJn
TRWOHaN8UYHOZsaRtBtopthZwSAcQqquUuGjGYjMbA6aRD8T14xFtExzuRacaVwM
NIAWsie3YZQFDGWvilONBHE8lPcYfmdqzIEWbg9Fff/hCpJufW5+YiRGplZerOs4
BMSJLaUAmKFeEqZXUEa+yT2XAoGAXRlyNCgSCKdrw9BKMHHgDW3kYIW3nxmvVsqv
7xnJOBBc52T/ekeIKHKyR2+VhslMndACzdwObv3bumK3lxVTmhjCwNGAaHs/i7iU
J9tEQ5y0O0F8C+tl5I7hrHikYkjoQ48RrM4ECcjjaKcSFATNqapYMK8NUkILiJkA
DeyityECgYAmvQrY8IBU94NVxx5hYzUC72JMApkc6D7PhU/UfGjm3EL55/EyNGcs
aIHwarqdvdUeOSnouuhhfHLoyyyUSx3g4KyRpZpM+yPWMFAm+dZkz1I0qctbFvRO
+YnNDdU6s2cIJ9wAYtr84QtYSpmtiBDwloP04P3w8TT3q1YMfij93Q==
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIEAjCCAuqgAwIBAgIRANNLpYRP6sc/Inl85QPEXJcwDQYJKoZIhvcNAQELBQAw
WzERMA8GA1UEChMIQXV0aGVsaWExFDASBgNVBAsTC0RldmVsb3BtZW50MTAwLgYD
VQQDEydBdXRoZWxpYSBEZXZlbG9wbWVudCBTdGFuZGFsb25lIFJvb3QgQ0EwIBcN
MDAwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMEExETAPBgNVBAoTCEF1dGhl
bGlhMRQwEgYDVQQLEwtEZXZlbG9wbWVudDEWMBQGA1UEAwwNKi5leGFtcGxlLmNv
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOonXWXyCONL+549NRJi
TZM1r02SZtlrJGz4voRZV6rmHpbbeiWbK7bX2rWGHK2gDOcHg+oq2MzSARLkEEO5
rYypWUJoBba03AOMRjKY40ITiNCybC4RjBmA8OWRUUx7h44QAFLAUIvIBBMAqKrd
rAv7IdU5Yqy4hqjwgOpULBXqGJlA7ODgumwTCp9HHktY0TgwfOOZKb9+zUDd3xKk
es9xK5gqElVDS/SBsHzNjHng4Nl9VtHidyOKIy6XRu52IZ8Dt4LldF8R1qkEO8ix
IxIn34r/BhT6ooD3/qlSQ4QcwXWJkObRn0WY2nzV5iPfOzZYaNPHhmddhOrCSXUI
45kCAwEAAaOB2DCB1TAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUH
AwEwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSWsFW3JNYlBZGKYt5levaas7PL
aDB/BgNVHREEeDB2gg0qLmV4YW1wbGUuY29tggtleGFtcGxlLmNvbYIOKi5leGFt
cGxlMS5jb22CDGV4YW1wbGUxLmNvbYIOKi5leGFtcGxlMi5jb22CDGV4YW1wbGUy
LmNvbYIOKi5leGFtcGxlMy5jb22CDGV4YW1wbGUzLmNvbTANBgkqhkiG9w0BAQsF
AAOCAQEAmUscEh131hh0MR6xsu4oIJO0SDTL43UNdsaZI5jarXEfmfVz18uSdjp1
tYVe7UJoi0iLMGzwIYcvnGv+HD91R7V0VFF78R+jHeAMtzGX/YDpUqjLBXXcPQ57
vUZIPxTE1V/qCd3MX1CHjfZEK2NbKvB3ciqBcryarbbAET65jCMtn1xk7KIFWEH7
Y2TuYMMi6QRYmep6u0LF2l61ZM7Awog31PBMrXRFQCVb8fS9KHnKthyS3BtdD2EU
xgxqkXnywhDQ2jTXGxKoQUIJnB/Niw38uQZAsLuyluncgjGKjYJ9eSacCZ+UJWeG
wVRoE07p3GTJAdnyPgeQqGG1gJP4lA==
-----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-----

View File

@ -0,0 +1,71 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA0x+u2Kkd1VZGkj7FDwgoXQp0fx1mx5VXd2VEJN9yYTXzlNRZ
Taw8WrOcud7hsBPw3DkhbCjEzvw0Ee+DjwtSCotKbtsBwjyLCegjluPHKUvsVNYZ
m19TxYY2erx7gohdEcmCGnpWSPRUAKBasIfpM0q6LXG70o8vTuKS82Ub++Sgl1Pa
kRL/e/KBUYFZksGEMK1oiPiOtRoJF+vUhRf46ZBg3aZ/HLNvcT5TAMgRRws+K3ek
C5+h5oXFexUosj2DCxcjTbsL7C5nqfR3jwmjrBaGN8KnloEDvC84+OsN/nE2PLa5
c1kTlRCvKd0gmRuucOKsJ6zvYf/hAqp/WCj1MQIDAQABAoIBAAOHCP3XvYbd/Sne
YJ6CrWH4lb+19wyooyB8kanoDdov85TuA1v3375IN/snDTBK9QBI+BT9jWRD9H7E
OLeAIevJLgIyKJJdPpl4xndz8NTwzs8QELd23Uh0mJ5uXcXtj1iHvGPC3YQ0iN7F
zx4Z9zyDKB8wQkofWFQCFyB39QK9ZGDW4ZstVb57fS62SuqFPW/rO2qSpsuUUwgy
Z2P2NqoqtqLIyw3qbsJCArzGoHuMCtjKDYenf8wJxORAsAGAREj71w2bQ20cMMIA
w30jgoXtEC9zS2BOb3mUBHiDOKnn4vwlNd7wiLPdZIGP75G4EkI4AHLhJQ1a5YuF
8E6V9AECgYEA1LSQVdWggvHTQnj5PHr5k7+YkL/MeIvOkLW5s0r7Lt3x45bAFaQh
XVZIXrynv62IZmTzCPwOwrXGJJieT0Ctom0XHgtp8nu7Okxk4AISRfjy7J03EXsJ
cS508IJ1B3HZepGvVwp+geJ0r9JmQ19JqZsJ7VENYoPKtYRZ9aV7CUECgYEA/hi1
Yw2FcSBk/kXVlcWvKtohY6NISgI5U1Kp7T16ZH3anpew6WwQ3GfueVet714BdwaZ
knqiiMvaTAOG66KYHCzRBSeXOozT/0N9AfKqS1y7xW+mR2nUrAiWCL95uZpB9SxE
3gylWULV4/+wlF006tEcJ5qiXymAAYv+wEg+f/ECgYBu2XLm6J/v3esFF1p8RHJQ
p2bw+KOspt+N1sbiQ09IC26F9wg/vvuMUu0AQj0BzYPqKO3nXsSqgGS0qbzG/KQA
o+2KQNSEBCt8pFdlzm6LfMPMv9n1CDPRgi57MOGgcZqvH8FLETMAqW26O2ID9mLD
OwMfZEAfeSNpGYJwXD8UgQKBgQC+0k1+Csx47YwKzOUeqivncZL7occLFWp5oa3N
ZYsB5uYEjgSk96wd6ctUwzzzc1SET6eLMp/XPcg9p7RuR1gWaK28QkQ3C0W2ALfj
e5raJ9U366YjIV4+p+AMx8chVLBN8CXz3+lZBHFe3Ul90hWIduu+7kkcUC06fCkf
u+F78QKBgFajhBPESe344ixG/fASpsVe2Yg14SgYCeWkinOe856zABY8dkfWWBIq
KX2eq1WJXErHWDuuNPP3Jol1CouqqHseqYQ+SaOhlHdoGws70bsIvBHrtj7NiEQZ
HFLhEk+OnnG+wJ1jQ5cseA4kbTuPjEL0NNVk7OSndiuxnnDbe91R
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIID3zCCAsegAwIBAgIQZjmlbZI+QaeqQpApxA2eDjANBgkqhkiG9w0BAQsFADBb
MREwDwYDVQQKEwhBdXRoZWxpYTEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxMDAuBgNV
BAMTJ0F1dGhlbGlhIERldmVsb3BtZW50IFN0YW5kYWxvbmUgUm9vdCBDQTAgFw0w
MDAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowRTERMA8GA1UEChMIQXV0aGVs
aWExFDASBgNVBAsTC0RldmVsb3BtZW50MRowGAYDVQQDExFsb2dpbi5leGFtcGxl
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANMfrtipHdVWRpI+
xQ8IKF0KdH8dZseVV3dlRCTfcmE185TUWU2sPFqznLne4bAT8Nw5IWwoxM78NBHv
g48LUgqLSm7bAcI8iwnoI5bjxylL7FTWGZtfU8WGNnq8e4KIXRHJghp6Vkj0VACg
WrCH6TNKui1xu9KPL07ikvNlG/vkoJdT2pES/3vygVGBWZLBhDCtaIj4jrUaCRfr
1IUX+OmQYN2mfxyzb3E+UwDIEUcLPit3pAufoeaFxXsVKLI9gwsXI027C+wuZ6n0
d48Jo6wWhjfCp5aBA7wvOPjrDf5xNjy2uXNZE5UQryndIJkbrnDirCes72H/4QKq
f1go9TECAwEAAaOBsjCBrzAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYB
BQUHAwEwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBSWsFW3JNYlBZGKYt5levaa
s7PLaDBZBgNVHREEUjBQghFsb2dpbi5leGFtcGxlLmNvbYISbG9naW4uZXhhbXBs
ZTEuY29tghJsb2dpbi5leGFtcGxlMi5jb22CDmxvZ2luLmV4YW1wbGUzggNjb20w
DQYJKoZIhvcNAQELBQADggEBAH46LB6fFF+5dbFhEa8rsDX17oZPVsIMHi+vhmMh
aS5IACOpmc3q/yyhZelNwB/MRzlPziQwpqwr9B5SQ9UOBvZDuv9ESXYHlVHSIGo9
+3Ax9fvxLVpF3E62whr+d8YHjXE85UgUKaDAWYCAVB7fkY7WfyS3t8IxgJVa+oMZ
sLeI4YmheKdgRZsE+83VcNUVuGhsh3R5NKFo46tonpbdx13Eg2k3IInKAkZmTA5D
YoPfPTDbd1BOC+h2C0s+guUyoG1Fi5DzS/x8xNoRcZ7/fkdcboAXa8dlVZeqGRky
ddYggjZYnqGaD9qKFAox4EqkCYB1XwNeUPUapdvGICC7UGc=
-----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-----

View File

@ -83,8 +83,8 @@ const (
)
const (
envFileProd = "./web/.env.production"
envFileDev = "./web/.env.development"
envFileProd = "/web/.env.production"
envFileDev = "/web/.env.development"
namespaceAuthelia = "authelia"
namespaceDashboard = "kubernetes-dashboard"
namespaceKube = "kube-system"

View File

@ -42,7 +42,7 @@ func waitUntilAutheliaBackendIsReady(dockerEnvironment *DockerEnvironment) error
90*time.Second,
dockerEnvironment,
"authelia-backend",
[]string{"Startup Complete"})
[]string{"Startup complete"})
}
func waitUntilAutheliaFrontendIsReady(dockerEnvironment *DockerEnvironment) error {

View File

@ -1,4 +1,4 @@
FROM golang:1.20.0-alpine
FROM golang:1.20.1-alpine
ARG USER_ID
ARG GROUP_ID

View File

@ -1,7 +1,7 @@
FROM caddy:2.6.3-builder AS builder
FROM caddy:2.6.4-builder AS builder
RUN xcaddy build fix-empty-copy-headers
FROM caddy:2.6.3
FROM caddy:2.6.4
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

View File

@ -3,7 +3,7 @@ version: '3'
services:
caddy:
# build: ./example/compose/caddy/ # used for debugging
image: caddy:2.6.3-alpine
image: caddy:2.6.4-alpine
volumes:
- ./example/compose/caddy/Caddyfile:/etc/caddy/Caddyfile
networks:

View File

@ -2,7 +2,7 @@
version: '3'
services:
envoy:
image: envoyproxy/envoy:v1.25.1
image: envoyproxy/envoy:v1.25.2
volumes:
- ./example/compose/envoy/envoy.yaml:/etc/envoy/envoy.yaml
- ./common/pki:/pki

View File

@ -125,7 +125,7 @@ static_resources:
common_tls_context:
tls_certificates:
- certificate_chain:
filename: /pki/public.bundle.crt
filename: /pki/public.chain.pem
private_key:
filename: /pki/private.pem
clusters:

View File

@ -1,12 +1,8 @@
FROM haproxy:2.7.2-alpine
FROM haproxy:2.7.3-alpine
USER root
RUN \
apk add --no-cache \
curl \
lua-json4 \
openssl && \
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=AU/ST=Victoria/L=Melbourne/O=Authelia/CN=*.example.com" -keyout haproxy.key -out haproxy.crt && \
cat haproxy.key haproxy.crt > /usr/local/etc/haproxy/haproxy.pem
lua-json4
USER haproxy
USER haproxy

View File

@ -7,6 +7,7 @@ services:
- ./example/compose/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
- ./example/compose/haproxy/http.lua:/usr/local/etc/haproxy/haproxy-lua-http/http.lua
- ./example/compose/haproxy/auth-request.lua:/usr/local/etc/haproxy/auth-request.lua
- ./common/pki:/pki
networks:
authelianet:
# Set the IP to be able to query on port 8080

View File

@ -2,10 +2,14 @@ global
lua-prepend-path /usr/local/etc/haproxy/?/http.lua
lua-load /usr/local/etc/haproxy/auth-request.lua
log stdout format raw local0 debug
maxconn 2000
defaults
default-server init-addr none
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
log global
option forwardfor
option httplog
@ -16,7 +20,7 @@ resolvers docker
nameserver ip 127.0.0.11:53
frontend fe_api
bind *:8081 ssl crt /usr/local/etc/haproxy/haproxy.pem
bind *:8081 ssl crt /pki/private.chain.pem
stats enable
stats uri /api
@ -24,7 +28,7 @@ frontend fe_api
stats admin if LOCALHOST
frontend fe_http
bind *:8080 ssl crt /usr/local/etc/haproxy/haproxy.pem
bind *:8080 ssl crt /pki/private.chain.pem
acl api-path path_beg -i /api
acl devworkflow-path path -i -m end /devworkflow

View File

@ -2,7 +2,7 @@
version: '3'
services:
mariadb:
image: mariadb:10.10.3
image: mariadb:10.11.2
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_USER=admin

View File

@ -16,7 +16,7 @@ http {
set $backend_endpoint https://authelia-backend:9091;
set $metrics_endpoint http://authelia-backend:9959;
ssl_certificate /pki/public.bundle.crt;
ssl_certificate /pki/public.chain.pem;
ssl_certificate_key /pki/private.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
@ -128,7 +128,7 @@ http {
resolver 127.0.0.11 ipv6=off;
set $upstream_endpoint http://nginx-backend;
ssl_certificate /pki/public.bundle.crt;
ssl_certificate /pki/public.chain.pem;
ssl_certificate_key /pki/private.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
@ -152,7 +152,7 @@ http {
set $upstream_endpoint http://nginx-backend;
set $upstream_headers http://httpbin:8000/headers;
ssl_certificate /pki/public.bundle.crt;
ssl_certificate /pki/public.chain.pem;
ssl_certificate_key /pki/private.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
@ -295,7 +295,7 @@ http {
set $upstream_authelia https://authelia-backend:9091/api/authz/auth-request;
set $upstream_endpoint http://oidc-client:8080;
ssl_certificate /pki/public.bundle.crt;
ssl_certificate /pki/public.chain.pem;
ssl_certificate_key /pki/private.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
@ -393,7 +393,7 @@ http {
resolver 127.0.0.11 ipv6=off;
set $upstream_endpoint http://smtp:1080;
ssl_certificate /pki/public.bundle.crt;
ssl_certificate /pki/public.chain.pem;
ssl_certificate_key /pki/private.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
@ -415,7 +415,7 @@ http {
resolver 127.0.0.11 ipv6=off;
set $upstream_endpoint http://duo-api:3000;
ssl_certificate /pki/public.bundle.crt;
ssl_certificate /pki/public.chain.pem;
ssl_certificate_key /pki/private.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
@ -434,7 +434,7 @@ http {
listen 8080 ssl;
server_name _;
ssl_certificate /pki/public.bundle.crt;
ssl_certificate /pki/public.chain.pem;
ssl_certificate_key /pki/private.pem;
return 301 https://home.example.com:8080/;

View File

@ -2,7 +2,7 @@
version: '3'
services:
traefik:
image: traefik:v2.9.6
image: traefik:v2.9.8
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'
labels:

View File

@ -18,7 +18,7 @@ spec:
spec:
containers:
- name: mariadb
image: mariadb:10.10.3
image: mariadb:10.11.2
ports:
- containerPort: 3306
readinessProbe:

View File

@ -7,61 +7,69 @@ import (
"testing"
"github.com/stretchr/testify/suite"
"github.com/valyala/fasthttp"
)
// WARNING: This scenario is intended to be used with TLS enabled in the authelia backend.
type BackendProtectionScenario struct {
suite.Suite
client *http.Client
}
func NewBackendProtectionScenario() *BackendProtectionScenario {
return &BackendProtectionScenario{}
}
func (s *BackendProtectionScenario) SetupSuite() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec // Needs to be enabled in suites. Not used in production.
}
s.client = &http.Client{
Transport: tr,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}
func (s *BackendProtectionScenario) AssertRequestStatusCode(method, url string, expectedStatusCode int) {
s.Run(url, func() {
req, err := http.NewRequest(method, url, nil)
s.Assert().NoError(err)
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec // Needs to be enabled in suites. Not used in production.
}
client := &http.Client{
Transport: tr,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
res, err := client.Do(req)
res, err := s.client.Do(req)
s.Assert().NoError(err)
s.Assert().Equal(expectedStatusCode, res.StatusCode)
})
}
func (s *BackendProtectionScenario) TestProtectionOfBackendEndpoints() {
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/secondfactor/totp", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/secondfactor/webauthn/assertion", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/secondfactor/webauthn/attestation", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/user/info/2fa_method", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/secondfactor/totp", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/secondfactor/webauthn/assertion", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/secondfactor/webauthn/attestation", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/user/info/2fa_method", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("GET", fmt.Sprintf("%s/api/user/info", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("GET", fmt.Sprintf("%s/api/configuration", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodGet, fmt.Sprintf("%s/api/user/info", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodGet, fmt.Sprintf("%s/api/configuration", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/secondfactor/totp/identity/start", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/secondfactor/totp/identity/finish", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/secondfactor/webauthn/identity/start", AutheliaBaseURL), 403)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/secondfactor/webauthn/identity/finish", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/secondfactor/totp/identity/start", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/secondfactor/totp/identity/finish", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/secondfactor/webauthn/identity/start", AutheliaBaseURL), 403)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/secondfactor/webauthn/identity/finish", AutheliaBaseURL), 403)
}
func (s *BackendProtectionScenario) TestInvalidEndpointsReturn404() {
s.AssertRequestStatusCode("GET", fmt.Sprintf("%s/api/not_existing", AutheliaBaseURL), 404)
s.AssertRequestStatusCode("HEAD", fmt.Sprintf("%s/api/not_existing", AutheliaBaseURL), 404)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/not_existing", AutheliaBaseURL), 404)
s.AssertRequestStatusCode(fasthttp.MethodGet, fmt.Sprintf("%s/api/not_existing", AutheliaBaseURL), 404)
s.AssertRequestStatusCode(fasthttp.MethodHead, fmt.Sprintf("%s/api/not_existing", AutheliaBaseURL), 404)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/not_existing", AutheliaBaseURL), 404)
s.AssertRequestStatusCode("GET", fmt.Sprintf("%s/api/not_existing/second", AutheliaBaseURL), 404)
s.AssertRequestStatusCode("HEAD", fmt.Sprintf("%s/api/not_existing/second", AutheliaBaseURL), 404)
s.AssertRequestStatusCode("POST", fmt.Sprintf("%s/api/not_existing/second", AutheliaBaseURL), 404)
s.AssertRequestStatusCode(fasthttp.MethodGet, fmt.Sprintf("%s/api/not_existing/second", AutheliaBaseURL), 404)
s.AssertRequestStatusCode(fasthttp.MethodHead, fmt.Sprintf("%s/api/not_existing/second", AutheliaBaseURL), 404)
s.AssertRequestStatusCode(fasthttp.MethodPost, fmt.Sprintf("%s/api/not_existing/second", AutheliaBaseURL), 404)
}
func (s *BackendProtectionScenario) TestInvalidEndpointsReturn405() {

View File

@ -0,0 +1,106 @@
package suites
import (
"crypto/tls"
"fmt"
"io"
"net/http"
"strings"
"testing"
"github.com/stretchr/testify/suite"
"github.com/valyala/fasthttp"
)
func NewRequestMethodScenario() *RequestMethodScenario {
return &RequestMethodScenario{}
}
type RequestMethodScenario struct {
suite.Suite
client *http.Client
}
func (s *RequestMethodScenario) SetupSuite() {
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec // Needs to be enabled in suites. Not used in production.
}
s.client = &http.Client{
Transport: tr,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}
func (s *RequestMethodScenario) TestShouldRespondWithAppropriateMethodNotAllowedHeaders() {
testCases := []struct {
name string
method string
uri string
expected []string
}{
{"RootPathShouldShowAllowedMethodsOnInvalidRequest", fasthttp.MethodPost, AutheliaBaseURL, []string{fasthttp.MethodGet, fasthttp.MethodHead, fasthttp.MethodOptions}},
{"OpenAPISpecificationShouldShowAllowedMethodsOnInvalidRequest", fasthttp.MethodPost, fmt.Sprintf("%s/api/openapi.yml", AutheliaBaseURL), []string{fasthttp.MethodGet, fasthttp.MethodHead, fasthttp.MethodOptions}},
{"LocalesShouldShowAllowedMethodsOnInvalidRequest", fasthttp.MethodPost, fmt.Sprintf("%s/locales/en/portal.json", AutheliaBaseURL), []string{fasthttp.MethodGet, fasthttp.MethodHead, fasthttp.MethodOptions}},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
req, err := http.NewRequest(tc.method, tc.uri, nil)
s.Assert().NoError(err)
res, err := s.client.Do(req)
s.Assert().NoError(err)
s.Assert().Equal(fasthttp.StatusMethodNotAllowed, res.StatusCode)
s.Assert().Equal(strings.Join(tc.expected, ", "), res.Header.Get(fasthttp.HeaderAllow))
})
}
}
func (s *RequestMethodScenario) TestShouldRespondWithAppropriateResponseWithMethodHEAD() {
testCases := []struct {
name string
uri string
expectedStatus int
expectedContentLength bool
}{
{"RootPathShouldShowContentLengthAndRespondOK", AutheliaBaseURL, fasthttp.StatusOK, true},
{"OpenAPISpecShouldShowContentLengthAndRespondOK", fmt.Sprintf("%s/api/openapi.yml", AutheliaBaseURL), fasthttp.StatusOK, true},
{"LocalesShouldShowContentLengthAndRespondOK", fmt.Sprintf("%s/locales/en/portal.json", AutheliaBaseURL), fasthttp.StatusOK, true},
}
for _, tc := range testCases {
s.Run(tc.name, func() {
req, err := http.NewRequest(fasthttp.MethodHead, tc.uri, nil)
s.Assert().NoError(err)
res, err := s.client.Do(req)
s.Assert().NoError(err)
s.Assert().Equal(tc.expectedStatus, res.StatusCode)
if tc.expectedContentLength {
s.Assert().NotEqual(0, res.ContentLength)
} else {
s.Assert().Equal(0, res.ContentLength)
}
data, err := io.ReadAll(res.Body)
s.Assert().NoError(err)
s.Assert().Len(data, 0)
})
}
}
func TestRunRequestMethod(t *testing.T) {
if testing.Short() {
t.Skip("skipping suite test in short mode")
}
suite.Run(t, NewRequestMethodScenario())
}

View File

@ -19,14 +19,12 @@ func init() {
"internal/suites/example/compose/samba/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, activedirectorySuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, activedirectorySuiteName); err != nil {
return err
}

View File

@ -19,14 +19,12 @@ func init() {
"internal/suites/example/compose/smtp/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, bypassAllSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, bypassAllSuiteName); err != nil {
return err
}

View File

@ -32,14 +32,12 @@ func init() {
})
}
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, caddySuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, caddySuiteName); err != nil {
return err
}

View File

@ -15,8 +15,8 @@ func init() {
"internal/suites/example/compose/authelia/docker-compose.backend.{}.yml",
})
setup := func(suitePath string) error {
if err := dockerEnvironment.Up(); err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}

View File

@ -43,25 +43,12 @@ func (s *CLISuite) SetupSuite() {
s.DockerEnvironment = dockerEnvironment
}
func (s *CLISuite) SetupTest() {
testArg := ""
coverageArg := ""
if os.Getenv("CI") == t {
testArg = "-test.coverprofile=/authelia/coverage-$(cat /proc/sys/kernel/random/uuid).txt"
coverageArg = "COVERAGE"
}
s.testArg = testArg
s.coverageArg = coverageArg
}
func (s *CLISuite) TestShouldPrintBuildInformation() {
if os.Getenv("CI") == "false" {
s.T().Skip("Skipping testing in dev environment")
}
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "build-info"})
output, err := s.Exec("authelia-backend", []string{"authelia", "build-info"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Last Tag: ")
s.Assert().Contains(output, "State: ")
@ -76,19 +63,19 @@ func (s *CLISuite) TestShouldPrintBuildInformation() {
}
func (s *CLISuite) TestShouldPrintVersion() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "--version"})
output, err := s.Exec("authelia-backend", []string{"authelia", "--version"})
s.Assert().NoError(err)
s.Assert().Contains(output, "authelia version")
}
func (s *CLISuite) TestShouldValidateConfig() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "validate-config"})
output, err := s.Exec("authelia-backend", []string{"authelia", "validate-config"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Configuration parsed and loaded successfully without errors.")
}
func (s *CLISuite) TestShouldFailValidateConfig() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "validate-config", "--config=/config/invalid.yml"})
output, err := s.Exec("authelia-backend", []string{"authelia", "validate-config", "--config=/config/invalid.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "failed to load configuration from file path(/config/invalid.yml) source: stat /config/invalid.yml: no such file or directory\n")
}
@ -99,37 +86,37 @@ func (s *CLISuite) TestShouldHashPasswordArgon2() {
err error
)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "argon2", "--password=apple123", "-m=32768"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "argon2", "--password=apple123", "-m=32768"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $argon2id$v=19$m=32768,t=3,p=4$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "argon2", "--password=apple123", "-m", "32768", "-v=argon2i"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "argon2", "--password=apple123", "-m", "32768", "-v=argon2i"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $argon2i$v=19$m=32768,t=3,p=4$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "argon2", "--password=apple123", "-m=32768", "-v=argon2d"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "argon2", "--password=apple123", "-m=32768", "-v=argon2d"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $argon2d$v=19$m=32768,t=3,p=4$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "argon2", "--random", "-m=32"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "argon2", "--random", "-m=32"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Random Password: ")
s.Assert().Contains(output, "Digest: $argon2id$v=19$m=32,t=3,p=4$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "argon2", "--password=apple123", "-p=1"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "argon2", "--password=apple123", "-p=1"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $argon2id$v=19$m=65536,t=3,p=1$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "argon2", "--password=apple123", "-i=1"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "argon2", "--password=apple123", "-i=1"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $argon2id$v=19$m=65536,t=1,p=4$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "argon2", "--password=apple123", "-s=64"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "argon2", "--password=apple123", "-s=64"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $argon2id$v=19$m=65536,t=3,p=4$")
s.Assert().GreaterOrEqual(len(output), 169)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "argon2", "--password=apple123", "-k=128"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "argon2", "--password=apple123", "-k=128"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $argon2id$v=19$m=65536,t=3,p=4$")
s.Assert().GreaterOrEqual(len(output), 233)
@ -141,33 +128,33 @@ func (s *CLISuite) TestShouldHashPasswordSHA2Crypt() {
err error
)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-v=sha256"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-v=sha256"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $5$rounds=50000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-v=sha512"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-v=sha512"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $6$rounds=50000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "sha2crypt", "--random", "-s=8"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "sha2crypt", "--random", "-s=8"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $6$rounds=50000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-i=10000"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-i=10000"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $6$rounds=10000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-s=20"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-s=20"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: errors occurred validating the password configuration: authentication_backend: file: password: sha2crypt: option 'salt_length' is configured as '20' but must be less than or equal to '16'")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-i=20"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-i=20"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: errors occurred validating the password configuration: authentication_backend: file: password: sha2crypt: option 'iterations' is configured as '20' but must be greater than or equal to '1000'")
}
func (s *CLISuite) TestShouldHashPasswordSHA2CryptSHA512() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-v=sha512"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "sha2crypt", "--password=apple123", "-v=sha512"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $6$rounds=50000$")
}
@ -178,28 +165,28 @@ func (s *CLISuite) TestShouldHashPasswordPBKDF2() {
err error
)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-v=sha1"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-v=sha1"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $pbkdf2$310000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "pbkdf2", "--random", "-v=sha256", "-i=100000"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "pbkdf2", "--random", "-v=sha256", "-i=100000"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Random Password: ")
s.Assert().Contains(output, "Digest: $pbkdf2-sha256$100000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-v=sha512", "-i=100000"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-v=sha512", "-i=100000"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $pbkdf2-sha512$100000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-v=sha224", "-i=100000"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-v=sha224", "-i=100000"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $pbkdf2-sha224$100000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-v=sha384", "-i=100000"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-v=sha384", "-i=100000"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $pbkdf2-sha384$100000$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-s=32", "-i=100000"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "pbkdf2", "--password=apple123", "-s=32", "-i=100000"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $pbkdf2-sha512$100000$")
}
@ -210,20 +197,20 @@ func (s *CLISuite) TestShouldHashPasswordBCrypt() {
err error
)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "bcrypt", "--password=apple123"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "bcrypt", "--password=apple123"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $2b$12$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "bcrypt", "--random", "-i=10"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "bcrypt", "--random", "-i=10"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Random Password: ")
s.Assert().Contains(output, "Digest: $2b$10$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "bcrypt", "--password=apple123", "-v=sha256"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "bcrypt", "--password=apple123", "-v=sha256"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $bcrypt-sha256$v=2,t=2b,r=12$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "bcrypt", "--random", "-v=sha256", "-i=10"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "bcrypt", "--random", "-v=sha256", "-i=10"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Random Password: ")
s.Assert().Contains(output, "Digest: $bcrypt-sha256$v=2,t=2b,r=10$")
@ -235,30 +222,30 @@ func (s *CLISuite) TestShouldHashPasswordSCrypt() {
err error
)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "scrypt", "--password=apple123"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "scrypt", "--password=apple123"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $scrypt$ln=16,r=8,p=1$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "scrypt", "--random"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "scrypt", "--random"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Random Password: ")
s.Assert().Contains(output, "Digest: $scrypt$ln=16,r=8,p=1$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "scrypt", "--password=apple123", "-i=1"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "scrypt", "--password=apple123", "-i=1"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $scrypt$ln=1,r=8,p=1$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "scrypt", "--password=apple123", "-i=1", "-p=2"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "scrypt", "--password=apple123", "-i=1", "-p=2"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $scrypt$ln=1,r=8,p=2$")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "hash", "generate", "scrypt", "--password=apple123", "-i=1", "-r=2"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "hash", "generate", "scrypt", "--password=apple123", "-i=1", "-r=2"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Digest: $scrypt$ln=1,r=2,p=1$")
}
func (s *CLISuite) TestShouldGenerateRSACertificateRequest() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "request", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "request", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate Request")
@ -273,7 +260,7 @@ func (s *CLISuite) TestShouldGenerateRSACertificateRequest() {
}
func (s *CLISuite) TestShouldGenerateECDSACurveP224CertificateRequest() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "request", "--curve=P224", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "request", "--curve=P224", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate Request")
@ -288,7 +275,7 @@ func (s *CLISuite) TestShouldGenerateECDSACurveP224CertificateRequest() {
}
func (s *CLISuite) TestShouldGenerateECDSACurveP256CertificateRequest() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "request", "--curve=P256", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "request", "--curve=P256", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate Request")
@ -303,7 +290,7 @@ func (s *CLISuite) TestShouldGenerateECDSACurveP256CertificateRequest() {
}
func (s *CLISuite) TestShouldGenerateECDSACurveP384CertificateRequest() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "request", "--curve=P384", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "request", "--curve=P384", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate Request")
@ -318,7 +305,7 @@ func (s *CLISuite) TestShouldGenerateECDSACurveP384CertificateRequest() {
}
func (s *CLISuite) TestShouldGenerateECDSACurveP521CertificateRequest() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "request", "--curve=P521", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "request", "--curve=P521", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate Request")
@ -333,7 +320,7 @@ func (s *CLISuite) TestShouldGenerateECDSACurveP521CertificateRequest() {
}
func (s *CLISuite) TestShouldGenerateEd25519CertificateRequest() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ed25519", "request", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ed25519", "request", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate Request")
@ -348,7 +335,7 @@ func (s *CLISuite) TestShouldGenerateEd25519CertificateRequest() {
}
func (s *CLISuite) TestShouldGenerateCertificateRSA() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -365,7 +352,7 @@ func (s *CLISuite) TestShouldGenerateCertificateRSA() {
}
func (s *CLISuite) TestShouldGenerateCertificateRSAWithIPAddress() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans", "*.example.com,127.0.0.1", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans", "*.example.com,127.0.0.1", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -382,7 +369,7 @@ func (s *CLISuite) TestShouldGenerateCertificateRSAWithIPAddress() {
}
func (s *CLISuite) TestShouldGenerateCertificateRSAWithNotBefore() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--not-before", "'Jan 1 15:04:05 2011'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--not-before", "'Jan 1 15:04:05 2011'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -400,13 +387,13 @@ 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/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "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: failed to find a suitable time layout for time 'Jan'")
}
func (s *CLISuite) TestShouldGenerateCertificateRSAWith4096Bits() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--bits=4096", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--bits=4096", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -423,7 +410,7 @@ func (s *CLISuite) TestShouldGenerateCertificateRSAWith4096Bits() {
}
func (s *CLISuite) TestShouldGenerateCertificateWithCustomizedSubject() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--country=Australia", "--organization='Acme Co.'", "--organizational-unit=Tech", "--province=QLD", "--street-address='123 Smith St'", "--postcode=4000", "--locality=Internet", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--country=Australia", "--organization='Acme Co.'", "--organizational-unit=Tech", "--province=QLD", "--street-address='123 Smith St'", "--postcode=4000", "--locality=Internet", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -440,7 +427,7 @@ func (s *CLISuite) TestShouldGenerateCertificateWithCustomizedSubject() {
}
func (s *CLISuite) TestShouldGenerateCertificateCA() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -457,7 +444,7 @@ func (s *CLISuite) TestShouldGenerateCertificateCA() {
}
func (s *CLISuite) TestShouldGenerateCertificateCAAndSignCertificate() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -472,7 +459,7 @@ func (s *CLISuite) TestShouldGenerateCertificateCAAndSignCertificate() {
s.Assert().Contains(output, "\tPrivate Key: /tmp/ca.private.pem")
s.Assert().Contains(output, "\tCertificate: /tmp/ca.public.crt")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--path.ca", "/tmp/", "--directory=/tmp/"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name=example.com", "--sans='*.example.com'", "--path.ca", "/tmp/", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -536,7 +523,7 @@ func (s *CLISuite) TestShouldGenerateCertificateCAAndSignCertificate() {
}
func (s *CLISuite) TestShouldGenerateCertificateEd25519() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ed25519", "generate", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ed25519", "generate", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -553,19 +540,19 @@ 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/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "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: failed to find a suitable time layout for time 'invalid'")
}
func (s *CLISuite) TestShouldFailGenerateCertificateECDSA() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=invalid", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "generate", "--curve=invalid", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: invalid curve 'invalid' was specified: curve must be P224, P256, P384, or P521")
}
func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP224() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=P224", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "generate", "--curve=P224", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -582,7 +569,7 @@ func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP224() {
}
func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP256() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=P256", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "generate", "--curve=P256", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -599,7 +586,7 @@ func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP256() {
}
func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP384() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=P384", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "generate", "--curve=P384", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -616,7 +603,7 @@ func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP384() {
}
func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP521() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "ecdsa", "generate", "--curve=P521", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "ecdsa", "generate", "--curve=P521", "--common-name=example.com", "--sans='*.example.com'", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating Certificate")
s.Assert().Contains(output, "\tSerial: ")
@ -633,7 +620,7 @@ func (s *CLISuite) TestShouldGenerateCertificateECDSACurveP521() {
}
func (s *CLISuite) TestShouldGenerateRSAKeyPair() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "rsa", "generate", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "rsa", "generate", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating key pair")
@ -645,7 +632,7 @@ func (s *CLISuite) TestShouldGenerateRSAKeyPair() {
}
func (s *CLISuite) TestShouldGenerateRSAKeyPairWith4069Bits() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "rsa", "generate", "--bits=4096", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "rsa", "generate", "--bits=4096", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating key pair")
@ -657,7 +644,7 @@ func (s *CLISuite) TestShouldGenerateRSAKeyPairWith4069Bits() {
}
func (s *CLISuite) TestShouldGenerateECDSAKeyPair() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "ecdsa", "generate", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating key pair")
@ -669,7 +656,7 @@ func (s *CLISuite) TestShouldGenerateECDSAKeyPair() {
}
func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP224() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=P224", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "ecdsa", "generate", "--curve=P224", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating key pair")
@ -681,7 +668,7 @@ func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP224() {
}
func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP256() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=P256", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "ecdsa", "generate", "--curve=P256", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating key pair")
@ -693,7 +680,7 @@ func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP256() {
}
func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP384() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=P384", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "ecdsa", "generate", "--curve=P384", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating key pair")
@ -705,7 +692,7 @@ func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP384() {
}
func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP521() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=P521", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "ecdsa", "generate", "--curve=P521", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating key pair")
@ -717,7 +704,7 @@ func (s *CLISuite) TestShouldGenerateECDSAKeyPairCurveP521() {
}
func (s *CLISuite) TestShouldGenerateEd25519KeyPair() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ed25519", "generate", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "ed25519", "generate", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Generating key pair")
@ -729,13 +716,13 @@ func (s *CLISuite) TestShouldGenerateEd25519KeyPair() {
}
func (s *CLISuite) TestShouldNotGenerateECDSAKeyPairCurveInvalid() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "pair", "ecdsa", "generate", "--curve=invalid", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "pair", "ecdsa", "generate", "--curve=invalid", "--directory=/tmp/"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: invalid curve 'invalid' was specified: curve must be P224, P256, P384, or P521")
}
func (s *CLISuite) TestShouldNotGenerateRSAWithBadCAPath() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/invalid", "--directory=/tmp/"})
output, err := s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/invalid", "--directory=/tmp/"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: could not read private key file '/tmp/invalid/ca.private.pem': open /tmp/invalid/ca.private.pem: no such file or directory\n")
}
@ -746,14 +733,14 @@ func (s *CLISuite) TestShouldNotGenerateRSAWithBadCAFileNames() {
output string
)
_, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"})
_, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"})
s.Assert().NoError(err)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-private-key=invalid.pem", "--directory=/tmp/"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-private-key=invalid.pem", "--directory=/tmp/"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: could not read private key file '/tmp/invalid.pem': open /tmp/invalid.pem: no such file or directory\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-certificate=invalid.crt", "--directory=/tmp/"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-certificate=invalid.crt", "--directory=/tmp/"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: could not read certificate file '/tmp/invalid.crt': open /tmp/invalid.crt: no such file or directory\n")
}
@ -764,17 +751,17 @@ func (s *CLISuite) TestShouldNotGenerateRSAWithBadCAFileContent() {
output string
)
_, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"})
_, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--common-name='Authelia Standalone Root Certificate Authority'", "--ca", "--directory=/tmp/"})
s.Assert().NoError(err)
s.Require().NoError(os.WriteFile("/tmp/ca.private.bad.pem", []byte("INVALID"), 0600)) //nolint:gosec
s.Require().NoError(os.WriteFile("/tmp/ca.public.bad.crt", []byte("INVALID"), 0600)) //nolint:gosec
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-private-key=ca.private.bad.pem", "--directory=/tmp/"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-private-key=ca.private.bad.pem", "--directory=/tmp/"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: could not parse private key from file '/tmp/ca.private.bad.pem': failed to parse PEM block containing the key\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-certificate=ca.public.bad.crt", "--directory=/tmp/"})
output, err = s.Exec("authelia-backend", []string{"authelia", "crypto", "certificate", "rsa", "generate", "--path.ca=/tmp/", "--file.ca-certificate=ca.public.bad.crt", "--directory=/tmp/"})
s.Assert().NotNil(err)
s.Assert().Contains(output, "Error: could not parse certificate from file '/tmp/ca.public.bad.crt': failed to parse PEM block containing the key\n")
}
@ -782,7 +769,7 @@ func (s *CLISuite) TestShouldNotGenerateRSAWithBadCAFileContent() {
func (s *CLISuite) TestStorage00ShouldShowCorrectPreInitInformation() {
_ = os.Remove("/tmp/db.sqlite3")
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config=/config/configuration.storage.yml"})
output, err := s.Exec("authelia-backend", []string{"authelia", "storage", "schema-info", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
pattern := regexp.MustCompile(`^Schema Version: N/A\nSchema Upgrade Available: yes - version \d+\nSchema Tables: N/A\nSchema Encryption Key: unsupported \(schema version\)`)
@ -790,45 +777,45 @@ func (s *CLISuite) TestStorage00ShouldShowCorrectPreInitInformation() {
s.Assert().Regexp(pattern, output)
patternOutdated := regexp.MustCompile(`Error: command requires the use of a up to date schema version: storage schema outdated: version \d+ is outdated please migrate to version \d+ in order to use this command or use an older binary`)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "totp", "export", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Regexp(patternOutdated, output)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "change-key", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Regexp(patternOutdated, output)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "check", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Regexp(regexp.MustCompile(`^Error: command requires the use of a up to date schema version: storage schema outdated: version 0 is outdated please migrate to version \d+ in order to use this command or use an older binary\n`), output)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "down", "--target=0", "--destroy-data", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "down", "--target=0", "--destroy-data", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: schema migration target version 0 is the same current version 0")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "up", "--target=2147483640", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "up", "--target=2147483640", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: schema up migration target version 2147483640 is greater then the latest version ")
s.Assert().Contains(output, " which indicates it doesn't exist")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "history", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "history", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "No migration history is available for schemas that not version 1 or above.\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "list-up", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "list-up", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Storage Schema Migration List (Up)\n\nVersion\t\tDescription\n1\t\tInitial Schema\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "list-down", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "list-down", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Storage Schema Migration List (Down)\n\nNo Migrations Available\n")
}
func (s *CLISuite) TestStorage01ShouldMigrateUp() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "up", "--config=/config/configuration.storage.yml"})
output, err := s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "up", "--config=/config/configuration.storage.yml"})
s.Require().NoError(err)
pattern0 := regexp.MustCompile(`"Storage schema migration from \d+ to \d+ is being attempted"`)
@ -837,23 +824,23 @@ func (s *CLISuite) TestStorage01ShouldMigrateUp() {
s.Regexp(pattern0, output)
s.Regexp(pattern1, output)
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "up", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "up", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: schema already up to date\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "history", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "history", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Migration History:\n\nID\tDate\t\t\t\tBefore\tAfter\tAuthelia Version\n")
s.Assert().Contains(output, "0\t1")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "list-up", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "list-up", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Storage Schema Migration List (Up)\n\nNo Migrations Available")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "list-down", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "list-down", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Storage Schema Migration List (Down)\n\nVersion\t\tDescription\n")
@ -861,7 +848,7 @@ func (s *CLISuite) TestStorage01ShouldMigrateUp() {
}
func (s *CLISuite) TestStorage02ShouldShowSchemaInfo() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config=/config/configuration.storage.yml"})
output, err := s.Exec("authelia-backend", []string{"authelia", "storage", "schema-info", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Schema Version: ")
@ -944,7 +931,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
for _, testCase := range testCases {
if testCase.png {
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "generate", testCase.config.Username, "--period", strconv.Itoa(int(testCase.config.Period)), "--algorithm", testCase.config.Algorithm, "--digits", strconv.Itoa(int(testCase.config.Digits)), "--path", qr, "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "totp", "generate", testCase.config.Username, "--period", strconv.Itoa(int(testCase.config.Period)), "--algorithm", testCase.config.Algorithm, "--digits", strconv.Itoa(int(testCase.config.Digits)), "--path", qr, "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, fmt.Sprintf(" and saved it as a PNG image at the path '%s'", qr))
@ -954,7 +941,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
s.Assert().False(fileInfo.IsDir())
s.Assert().Greater(fileInfo.Size(), int64(1000))
} else {
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "generate", testCase.config.Username, "--period", strconv.Itoa(int(testCase.config.Period)), "--algorithm", testCase.config.Algorithm, "--digits", strconv.Itoa(int(testCase.config.Digits)), "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "totp", "generate", testCase.config.Username, "--period", strconv.Itoa(int(testCase.config.Period)), "--algorithm", testCase.config.Algorithm, "--digits", strconv.Itoa(int(testCase.config.Digits)), "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
}
@ -968,11 +955,11 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
}
yml := filepath.Join(dir, "authelia.export.totp.yaml")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "--file", yml, "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "totp", "export", "--file", yml, "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d TOTP configurations as YAML to the '%s' file\n", len(expectedLines), yml))
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "uri", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "totp", "export", "uri", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
for _, expectedLine := range expectedLines {
@ -980,7 +967,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
}
csv := filepath.Join(dir, "authelia.export.totp.csv")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "csv", "--file", csv, "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "totp", "export", "csv", "--file", csv, "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d TOTP configurations as CSV to the '%s' file\n", len(expectedLines), csv))
@ -996,7 +983,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
pngs := filepath.Join(dir, "png-qr-codes")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "export", "png", "--directory", pngs, "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "totp", "export", "png", "--directory", pngs, "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d TOTP configuration as QR codes in PNG format to the '%s' directory\n", len(expectedLines), pngs))
@ -1010,7 +997,7 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
s.Assert().Greater(fileInfo.Size(), int64(1000))
}
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "totp", "generate", "test", "--period=30", "--algorithm=SHA1", "--digits=6", "--path", qr, "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "totp", "generate", "test", "--period=30", "--algorithm=SHA1", "--digits=6", "--path", qr, "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: image output filepath already exists")
}
@ -1018,56 +1005,56 @@ func (s *CLISuite) TestStorage03ShouldExportTOTP() {
func (s *CLISuite) TestStorage04ShouldManageUniqueID() {
dir := s.T().TempDir()
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file=out.yml", "--config=/config/configuration.storage.yml"})
output, err := s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "export", "--file=out.yml", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: no data to export")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "add", "john", "--service=webauthn", "--sector=''", "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "add", "john", "--service=webauthn", "--sector=''", "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: the service name 'webauthn' is invalid, the valid values are: 'openid'")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector=''", "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector=''", "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Added User Opaque Identifier:\n\tService: openid\n\tSector: \n\tUsername: john\n\tIdentifier: 1097c8f8-83f2-4506-8138-5f40e83a1285\n\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file=/a/no/path/fileout.yml", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "export", "--file=/a/no/path/fileout.yml", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: error occurred writing to file '/a/no/path/fileout.yml': open /a/no/path/fileout.yml: no such file or directory")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file=out.yml", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "export", "--file=out.yml", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: error occurred writing to file 'out.yml': open out.yml: permission denied")
out1 := filepath.Join(dir, "1.yml")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file", out1, "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "export", "--file", out1, "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d User Opaque Identifiers as YAML to the '%s' file\n", 1, out1))
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file", out1, "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "export", "--file", out1, "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, fmt.Sprintf("Error: must specify a file that doesn't exist but '%s' exists", out1))
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector=''", "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector=''", "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: error inserting user opaque id for user 'john' with opaque id '1097c8f8-83f2-4506-8138-5f40e83a1285':")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector=''", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector=''", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: error inserting user opaque id for user 'john' with opaque id")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector='openidconnect.com'", "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector='openidconnect.com'", "--identifier=1097c8f8-83f2-4506-8138-5f40e83a1285", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: error inserting user opaque id for user 'john' with opaque id '1097c8f8-83f2-4506-8138-5f40e83a1285':")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector='openidconnect.net'", "--identifier=b0e17f48-933c-4cba-8509-ee9bfadf8ce5", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector='openidconnect.net'", "--identifier=b0e17f48-933c-4cba-8509-ee9bfadf8ce5", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Added User Opaque Identifier:\n\tService: openid\n\tSector: openidconnect.net\n\tUsername: john\n\tIdentifier: b0e17f48-933c-4cba-8509-ee9bfadf8ce5\n\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector='bad-uuid.com'", "--identifier=d49564dc-b7a1-11ec-8429-fcaa147128ea", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector='bad-uuid.com'", "--identifier=d49564dc-b7a1-11ec-8429-fcaa147128ea", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: the identifier providerd 'd49564dc-b7a1-11ec-8429-fcaa147128ea' is a version 1 UUID but only version 4 UUID's accepted as identifiers")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector='bad-uuid.com'", "--identifier=asdmklasdm", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "add", "john", "--service=openid", "--sector='bad-uuid.com'", "--identifier=asdmklasdm", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: the identifier provided 'asdmklasdm' is invalid as it must be a version 4 UUID but parsing it had an error: invalid UUID length: 10")
@ -1086,7 +1073,7 @@ func (s *CLISuite) TestStorage04ShouldManageUniqueID() {
s.Assert().Equal("openid", export.Identifiers[0].Service)
out2 := filepath.Join(dir, "2.yml")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "user", "identifiers", "export", "--file", out2, "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "user", "identifiers", "export", "--file", out2, "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, fmt.Sprintf("Successfully exported %d User Opaque Identifiers as YAML to the '%s' file\n", 2, out2))
@ -1111,12 +1098,12 @@ func (s *CLISuite) TestStorage04ShouldManageUniqueID() {
}
func (s *CLISuite) TestStorage05ShouldChangeEncryptionKey() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--new-encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
output, err := s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "change-key", "--new-encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Completed the encryption key change. Please adjust your configuration to use the new key.\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "schema-info", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "schema-info", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Schema Version: ")
@ -1131,12 +1118,12 @@ func (s *CLISuite) TestStorage05ShouldChangeEncryptionKey() {
s.Assert().Contains(output, "totp_configurations")
s.Assert().Contains(output, "Schema Encryption Key: invalid")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "check", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Storage Encryption Key Validation: FAILURE\n\n\tCause: the configured encryption key does not appear to be valid for this database which may occur if the encryption key was changed in the configuration without using the cli to change it in the database.\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--verbose", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "check", "--verbose", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Storage Encryption Key Validation: FAILURE\n\n\tCause: the configured encryption key does not appear to be valid for this database which may occur if the encryption key was changed in the configuration without using the cli to change it in the database.\n\nTables:\n\n")
@ -1148,12 +1135,12 @@ func (s *CLISuite) TestStorage05ShouldChangeEncryptionKey() {
s.Assert().Contains(output, "\n\n\tTable (totp_configurations): FAILURE\n\t\tInvalid Rows: 4\n\t\tTotal Rows: 4\n")
s.Assert().Contains(output, "\n\n\tTable (webauthn_devices): N/A\n\t\tInvalid Rows: 0\n\t\tTotal Rows: 0\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "check", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Storage Encryption Key Validation: SUCCESS\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "check", "--verbose", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "check", "--verbose", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
s.Assert().Contains(output, "Storage Encryption Key Validation: SUCCESS\n\nTables:\n\n")
@ -1165,19 +1152,19 @@ func (s *CLISuite) TestStorage05ShouldChangeEncryptionKey() {
s.Assert().Contains(output, "\n\n\tTable (totp_configurations): SUCCESS\n\t\tInvalid Rows: 0\n\t\tTotal Rows: 4\n")
s.Assert().Contains(output, "\n\n\tTable (webauthn_devices): N/A\n\t\tInvalid Rows: 0\n\t\tTotal Rows: 0\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "change-key", "--encryption-key=apple-apple-apple-apple", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: you must either use an interactive terminal or use the --new-encryption-key flag\n")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "encryption", "change-key", "--encryption-key=apple-apple-apple-apple", "--new-encryption-key=abc", "--config=/config/configuration.storage.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "storage", "encryption", "change-key", "--encryption-key=apple-apple-apple-apple", "--new-encryption-key=abc", "--config=/config/configuration.storage.yml"})
s.Assert().EqualError(err, "exit status 1")
s.Assert().Contains(output, "Error: the new encryption key must be at least 20 characters\n")
}
func (s *CLISuite) TestStorage06ShouldMigrateDown() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "storage", "migrate", "down", "--target=0", "--destroy-data", "--config=/config/configuration.storage.yml"})
output, err := s.Exec("authelia-backend", []string{"authelia", "storage", "migrate", "down", "--target=0", "--destroy-data", "--config=/config/configuration.storage.yml"})
s.Assert().NoError(err)
pattern0 := regexp.MustCompile(`"Storage schema migration from \d+ to \d+ is being attempted"`)
@ -1188,7 +1175,7 @@ func (s *CLISuite) TestStorage06ShouldMigrateDown() {
}
func (s *CLISuite) TestACLPolicyCheckVerbose() {
output, err := s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://public.example.com", "--verbose", "--config=/config/configuration.yml"})
output, err := s.Exec("authelia-backend", []string{"authelia", "access-control", "check-policy", "--url=https://public.example.com", "--verbose", "--config=/config/configuration.yml"})
s.Assert().NoError(err)
// This is an example of `authelia access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://public.example.com --verbose`.
@ -1205,7 +1192,7 @@ func (s *CLISuite) TestACLPolicyCheckVerbose() {
s.Contains(output, " 9\tmiss\thit\t\thit\thit\tmay\n")
s.Contains(output, "The policy 'bypass' from rule #1 will be applied to this request.")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://admin.example.com", "--method=HEAD", "--username=tom", "--groups=basic,test", "--ip=192.168.2.3", "--verbose", "--config=/config/configuration.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "access-control", "check-policy", "--url=https://admin.example.com", "--method=HEAD", "--username=tom", "--groups=basic,test", "--ip=192.168.2.3", "--verbose", "--config=/config/configuration.yml"})
s.Assert().NoError(err)
// This is an example of `authelia access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://admin.example.com --method=HEAD --username=tom --groups=basic,test --ip=192.168.2.3 --verbose`.
@ -1223,7 +1210,7 @@ func (s *CLISuite) TestACLPolicyCheckVerbose() {
s.Contains(output, " 9\tmiss\thit\t\thit\thit\tmiss\n")
s.Contains(output, "The policy 'two_factor' from rule #2 will be applied to this request.")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://resources.example.com/resources/test", "--method=POST", "--username=john", "--groups=admin,test", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "access-control", "check-policy", "--url=https://resources.example.com/resources/test", "--method=POST", "--username=john", "--groups=admin,test", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
s.Assert().NoError(err)
// This is an example of `authelia access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://resources.example.com/resources/test --method=POST --username=john --groups=admin,test --ip=192.168.1.3 --verbose`.
@ -1240,7 +1227,7 @@ func (s *CLISuite) TestACLPolicyCheckVerbose() {
s.Contains(output, " 9\tmiss\thit\t\thit\thit\thit\n")
s.Contains(output, "The policy 'one_factor' from rule #5 will be applied to this request.")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://user.example.com/resources/test", "--method=HEAD", "--username=john", "--groups=admin,test", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "access-control", "check-policy", "--url=https://user.example.com/resources/test", "--method=HEAD", "--username=john", "--groups=admin,test", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
s.Assert().NoError(err)
// This is an example of `access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://user.example.com --method=HEAD --username=john --groups=admin,test --ip=192.168.1.3 --verbose`.
@ -1257,7 +1244,7 @@ func (s *CLISuite) TestACLPolicyCheckVerbose() {
s.Contains(output, "* 9\thit\thit\t\thit\thit\thit\n")
s.Contains(output, "The policy 'one_factor' from rule #9 will be applied to this request.")
output, err = s.Exec("authelia-backend", []string{"authelia", s.testArg, s.coverageArg, "access-control", "check-policy", "--url=https://user.example.com", "--method=HEAD", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
output, err = s.Exec("authelia-backend", []string{"authelia", "access-control", "check-policy", "--url=https://user.example.com", "--method=HEAD", "--ip=192.168.1.3", "--verbose", "--config=/config/configuration.yml"})
s.Assert().NoError(err)
// This is an example of `authelia access-control check-policy --config .\internal\suites\CLI\configuration.yml --url=https://user.example.com --method=HEAD --ip=192.168.1.3 --verbose`.

View File

@ -18,14 +18,12 @@ func init() {
"internal/suites/example/compose/smtp/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, dockerSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, dockerSuiteName); err != nil {
return err
}

View File

@ -19,14 +19,12 @@ func init() {
"internal/suites/example/compose/duo-api/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, duoPushSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, duoPushSuiteName); err != nil {
return err
}

View File

@ -32,14 +32,12 @@ func init() {
})
}
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, envoySuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, envoySuiteName); err != nil {
return err
}

View File

@ -32,14 +32,12 @@ func init() {
})
}
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, haproxySuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, haproxySuiteName); err != nil {
return err
}

View File

@ -23,14 +23,12 @@ var haDockerEnvironment = NewDockerEnvironment([]string{
})
func init() {
setup := func(suitePath string) error {
err := haDockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = haDockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(haDockerEnvironment, highAvailabilitySuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(haDockerEnvironment, highAvailabilitySuiteName); err != nil {
return err
}

View File

@ -20,14 +20,12 @@ func init() {
"internal/suites/example/compose/ldap/docker-compose.admin.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, ldapSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, ldapSuiteName); err != nil {
return err
}

View File

@ -20,14 +20,12 @@ func init() {
"internal/suites/example/compose/ldap/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, mariadbSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, mariadbSuiteName); err != nil {
return err
}

View File

@ -18,13 +18,16 @@ var multiCookieDomainDockerEnvironment = NewDockerEnvironment([]string{
})
func init() {
setup := func(suitePath string) error {
err := multiCookieDomainDockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = multiCookieDomainDockerEnvironment.Up(); err != nil {
return err
}
return waitUntilAutheliaIsReady(multiCookieDomainDockerEnvironment, multiCookieDomainSuiteName)
if err = waitUntilAutheliaIsReady(multiCookieDomainDockerEnvironment, multiCookieDomainSuiteName); err != nil {
return err
}
return updateDevEnvFileForDomain(BaseDomain, true)
}
displayAutheliaLogs := func() error {

View File

@ -20,14 +20,12 @@ func init() {
"internal/suites/example/compose/ldap/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, mysqlSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, mysqlSuiteName); err != nil {
return err
}

View File

@ -21,14 +21,12 @@ func init() {
"internal/suites/example/compose/httpbin/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, networkACLSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, networkACLSuiteName); err != nil {
return err
}

View File

@ -20,21 +20,18 @@ func init() {
"internal/suites/example/compose/redis/docker-compose.yml",
})
setup := func(suitePath string) error {
setup := func(suitePath string) (err error) {
// TODO(c.michaud): use version in tags for oidc-client but in the meantime we pull the image to make sure it's
// up to date.
err := dockerEnvironment.Pull("oidc-client")
if err != nil {
if err = dockerEnvironment.Pull("oidc-client"); err != nil {
return err
}
err = dockerEnvironment.Up()
if err != nil {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, oidcSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, oidcSuiteName); err != nil {
return err
}

View File

@ -34,21 +34,18 @@ func init() {
})
}
setup := func(suitePath string) error {
setup := func(suitePath string) (err error) {
// TODO(c.michaud): use version in tags for oidc-client but in the meantime we pull the image to make sure it's
// up to date.
err := dockerEnvironment.Pull("oidc-client")
if err != nil {
if err = dockerEnvironment.Pull("oidc-client"); err != nil {
return err
}
err = dockerEnvironment.Up()
if err != nil {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, oidcTraefikSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, oidcTraefikSuiteName); err != nil {
return err
}

View File

@ -17,14 +17,12 @@ func init() {
"internal/suites/example/compose/nginx/portal/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, oneFactorOnlySuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, oneFactorOnlySuiteName); err != nil {
return err
}

View File

@ -32,14 +32,12 @@ func init() {
})
}
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, pathPrefixSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, pathPrefixSuiteName); err != nil {
return err
}

View File

@ -20,14 +20,12 @@ func init() {
"internal/suites/example/compose/ldap/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, postgresSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, postgresSuiteName); err != nil {
return err
}

View File

@ -18,14 +18,12 @@ func init() {
"internal/suites/example/compose/smtp/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, shortTimeoutsSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, shortTimeoutsSuiteName); err != nil {
return err
}

View File

@ -23,14 +23,12 @@ func init() {
"internal/suites/example/compose/smtp/docker-compose.yml",
})
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, standaloneSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, standaloneSuiteName); err != nil {
return err
}

View File

@ -346,6 +346,10 @@ func (s *StandaloneSuite) TestResetPasswordScenario() {
suite.Run(s.T(), NewResetPasswordScenario())
}
func (s *StandaloneSuite) TestRequestMethodScenario() {
suite.Run(s.T(), NewRequestMethodScenario())
}
func (s *StandaloneSuite) TestAvailableMethodsScenario() {
suite.Run(s.T(), NewAvailableMethodsScenario([]string{"TIME-BASED ONE-TIME PASSWORD", "SECURITY KEY - WEBAUTHN"}))
}

View File

@ -32,14 +32,12 @@ func init() {
})
}
setup := func(suitePath string) error {
err := dockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = dockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(dockerEnvironment, traefikSuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(dockerEnvironment, traefikSuiteName); err != nil {
return err
}

View File

@ -34,14 +34,12 @@ func init() {
})
}
setup := func(suitePath string) error {
err := traefik2DockerEnvironment.Up()
if err != nil {
setup := func(suitePath string) (err error) {
if err = traefik2DockerEnvironment.Up(); err != nil {
return err
}
err = waitUntilAutheliaIsReady(traefik2DockerEnvironment, traefik2SuiteName)
if err != nil {
if err = waitUntilAutheliaIsReady(traefik2DockerEnvironment, traefik2SuiteName); err != nil {
return err
}

View File

@ -31,8 +31,5 @@ type BaseSuite struct {
type CommandSuite struct {
*BaseSuite
testArg string //nolint:structcheck // TODO: Remove when bug fixed: https://github.com/golangci/golangci-lint/issues/537.
coverageArg string //nolint:structcheck // TODO: Remove when bug fixed: https://github.com/golangci/golangci-lint/issues/537.
*DockerEnvironment
}

View File

@ -241,8 +241,8 @@ func fixCoveragePath(path string, file os.FileInfo, err error) error {
// getEnvInfoFromURL gets environments variables for specified cookie domain
// this func makes a http call to https://login.<domain>/devworkflow and is only useful for suite tests.
func getDomainEnvInfo(domain string) (map[string]string, error) {
info := make(map[string]string)
func getDomainEnvInfo(domain string) (info map[string]string, err error) {
info = make(map[string]string)
client := &http.Client{
Transport: &http.Transport{
@ -256,7 +256,6 @@ func getDomainEnvInfo(domain string) (map[string]string, error) {
req *http.Request
resp *http.Response
body []byte
err error
)
targetURL := LoginBaseURLFmt(domain) + "/devworkflow"
@ -285,16 +284,20 @@ func getDomainEnvInfo(domain string) (map[string]string, error) {
}
// generateDevEnvFile generates web/.env.development based on opts.
func generateDevEnvFile(opts map[string]string) error {
tmpl, err := template.ParseFiles(envFileProd)
if err != nil {
func generateDevEnvFile(info map[string]string) (err error) {
base, _ := os.Getwd()
base = strings.TrimSuffix(base, "/internal/suites")
var tmpl *template.Template
if tmpl, err = template.ParseFiles(base + envFileProd); err != nil {
return err
}
file, _ := os.Create(envFileDev)
file, _ := os.Create(base + envFileDev)
defer file.Close()
if err := tmpl.Execute(file, opts); err != nil {
if err = tmpl.Execute(file, info); err != nil {
return err
}
@ -303,29 +306,28 @@ func generateDevEnvFile(opts map[string]string) error {
// updateDevEnvFileForDomain updates web/.env.development.
// this function only affects local dev environments.
func updateDevEnvFileForDomain(domain string, setup bool) error {
func updateDevEnvFileForDomain(domain string, setup bool) (err error) {
if os.Getenv("CI") == t {
return nil
}
if _, err := os.Stat(envFileDev); err != nil && os.IsNotExist(err) {
if _, err = os.Stat(envFileDev); err != nil && os.IsNotExist(err) {
file, _ := os.Create(envFileDev)
file.Close()
}
info, err := getDomainEnvInfo(domain)
if err != nil {
var info map[string]string
if info, err = getDomainEnvInfo(domain); err != nil {
return err
}
err = generateDevEnvFile(info)
if err != nil {
if err = generateDevEnvFile(info); err != nil {
return err
}
if !setup {
err = waitUntilAutheliaFrontendIsReady(multiCookieDomainDockerEnvironment)
if err != nil {
if err = waitUntilAutheliaFrontendIsReady(multiCookieDomainDockerEnvironment); err != nil {
return err
}
}

View File

@ -231,18 +231,30 @@ func IsX509PrivateKey(i any) bool {
// WriteCertificateBytesToPEM writes a certificate/csr to a file in the PEM format.
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)
}
blockType := BlockTypeCertificate
if csr {
blockType = BlockTypeCertificateRequest
}
for _, cert := range certs {
if err = pem.Encode(out, &pem.Block{Bytes: cert, Type: blockType}); err != nil {
blocks := make([]*pem.Block, len(certs))
for i, cert := range certs {
blocks[i] = &pem.Block{Type: blockType, Bytes: cert}
}
return WritePEM(path, blocks...)
}
// WritePEM writes a set of *pem.Blocks to a file.
func WritePEM(path string, blocks ...*pem.Block) (err error) {
var out *os.File
if out, err = os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
return err
}
for _, block := range blocks {
if err = pem.Encode(out, block); err != nil {
_ = out.Close()
return err
@ -254,23 +266,12 @@ func WriteCertificateBytesToPEM(path string, csr bool, certs ...[]byte) (err err
// WriteKeyToPEM writes a key that can be encoded as a PEM to a file in the PEM format.
func WriteKeyToPEM(key any, path string, pkcs8 bool) (err error) {
pemBlock, err := PEMBlockFromX509Key(key, pkcs8)
block, err := PEMBlockFromX509Key(key, pkcs8)
if err != nil {
return err
}
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return fmt.Errorf("failed to open %s for writing: %w", path, err)
}
if err = pem.Encode(out, pemBlock); err != nil {
_ = out.Close()
return err
}
return out.Close()
return WritePEM(path, block)
}
// PEMBlockFromX509Key turns a PublicKey or PrivateKey into a pem.Block.

View File

@ -19,27 +19,27 @@
},
"dependencies": {
"@emotion/cache": "11.10.5",
"@emotion/react": "11.10.5",
"@emotion/styled": "11.10.5",
"@emotion/react": "11.10.6",
"@emotion/styled": "11.10.6",
"@fortawesome/fontawesome-svg-core": "6.3.0",
"@fortawesome/free-regular-svg-icons": "6.3.0",
"@fortawesome/free-solid-svg-icons": "6.3.0",
"@fortawesome/react-fontawesome": "0.2.0",
"@mui/icons-material": "5.11.0",
"@mui/material": "5.11.8",
"@mui/styles": "5.11.7",
"axios": "1.3.2",
"@mui/icons-material": "5.11.11",
"@mui/material": "5.11.11",
"@mui/styles": "5.11.11",
"axios": "1.3.4",
"broadcast-channel": "4.20.2",
"classnames": "2.3.2",
"i18next": "22.4.9",
"i18next": "22.4.10",
"i18next-browser-languagedetector": "7.0.1",
"i18next-http-backend": "2.1.1",
"qrcode.react": "3.1.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-i18next": "12.1.5",
"react-i18next": "12.2.0",
"react-loading": "2.0.3",
"react-router-dom": "6.8.1",
"react-router-dom": "6.8.2",
"react18-input-otp": "1.1.2",
"zxcvbn": "4.4.2"
},
@ -142,23 +142,23 @@
]
},
"devDependencies": {
"@commitlint/cli": "17.4.2",
"@commitlint/config-conventional": "17.4.2",
"@commitlint/cli": "17.4.4",
"@commitlint/config-conventional": "17.4.4",
"@limegrass/eslint-plugin-import-alias": "1.0.6",
"@testing-library/jest-dom": "5.16.5",
"@testing-library/react": "13.4.0",
"@testing-library/react": "14.0.0",
"@types/jest": "29.4.0",
"@types/node": "18.13.0",
"@types/node": "18.14.4",
"@types/qrcode.react": "1.0.2",
"@types/react": "18.0.28",
"@types/react-dom": "18.0.10",
"@types/react-dom": "18.0.11",
"@types/zxcvbn": "4.4.1",
"@typescript-eslint/eslint-plugin": "5.51.0",
"@typescript-eslint/parser": "5.51.0",
"@typescript-eslint/eslint-plugin": "5.54.0",
"@typescript-eslint/parser": "5.54.0",
"@vitejs/plugin-react": "3.1.0",
"esbuild": "0.17.7",
"esbuild": "0.17.10",
"esbuild-jest": "0.5.0",
"eslint": "8.34.0",
"eslint": "8.35.0",
"eslint-config-prettier": "8.6.0",
"eslint-config-react-app": "7.0.1",
"eslint-formatter-rdjson": "1.0.5",
@ -169,16 +169,16 @@
"eslint-plugin-react": "7.32.2",
"eslint-plugin-react-hooks": "4.6.0",
"husky": "8.0.3",
"jest": "29.4.2",
"jest-environment-jsdom": "29.4.2",
"jest": "29.4.3",
"jest-environment-jsdom": "29.4.3",
"jest-transform-stub": "2.0.0",
"jest-watch-typeahead": "2.2.2",
"prettier": "2.8.4",
"react-test-renderer": "18.2.0",
"typescript": "4.9.5",
"vite": "4.1.1",
"vite": "4.1.4",
"vite-plugin-eslint": "1.8.1",
"vite-plugin-istanbul": "4.0.0",
"vite-plugin-istanbul": "4.0.1",
"vite-plugin-svgr": "2.4.0",
"vite-tsconfig-paths": "4.0.5"
}

File diff suppressed because it is too large Load Diff