refactor: path from address (#5492)

Signed-off-by: James Elliott <james-d-elliott@users.noreply.github.com>
pull/5496/head^2
James Elliott 2023-05-30 18:21:19 +10:00 committed by GitHub
parent f90c369b45
commit 4577fce95b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 233 additions and 524 deletions

View File

@ -7,5 +7,5 @@
package cmd package cmd
const ( const (
versionSwaggerUI = "4.18.3" versionSwaggerUI = "4.19.0"
) )

View File

@ -47,15 +47,12 @@ default_redirection_url: 'https://home.example.com/'
server: server:
## The address for the Main server to listen on in the address common syntax. ## The address for the Main server to listen on in the address common syntax.
## Formats: ## Formats:
## - [<scheme>://]<hostname>[:<port>] ## - [<scheme>://]<hostname>[:<port>][/<path>]
## - [<scheme>://][hostname]:<port> ## - [<scheme>://][hostname]:<port>[/<path>]
## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'. ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'.
## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9091'. ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9091'.
address: 'tcp://:9091' ## If the path is specified this configures the router to handle both the `/` path and the configured path.
address: 'tcp://:9091/'
## Set the single level path Authelia listens on.
## Must be alphanumeric chars and should not contain any slashes.
path: ''
## Set the path on disk to Authelia assets. ## Set the path on disk to Authelia assets.
## Useful to allow overriding of specific static assets. ## Useful to allow overriding of specific static assets.
@ -162,11 +159,12 @@ telemetry:
## The address for the Metrics server to listen on in the address common syntax. ## The address for the Metrics server to listen on in the address common syntax.
## Formats: ## Formats:
## - [<scheme>://]<hostname>[:<port>] ## - [<scheme>://]<hostname>[:<port>][/<path>]
## - [<scheme>://][hostname]:<port> ## - [<scheme>://][hostname]:<port>[/<path>]
## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'. ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'.
## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9959'. ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9959'.
address: 'tcp://:9959' ## If the path is not specified it defaults to `/metrics`.
address: 'tcp://:9959/metrics'
## Metrics Server Buffers configuration. ## Metrics Server Buffers configuration.
# buffers: # buffers:

View File

@ -21,8 +21,7 @@ aliases:
```yaml ```yaml
server: server:
address: 'tcp://:9091' address: 'tcp://:9091/'
path: ''
disable_healthcheck: false disable_healthcheck: false
tls: tls:
key: '' key: ''
@ -59,19 +58,25 @@ server:
### address ### address
{{< confkey type="address" default="tcp://:9091" required="no" >}} {{< confkey type="address" default="tcp://:9091/" required="no" >}}
*__Reference Note:__ This configuration option uses the [address common syntax](../prologue/common.md#address). Please *__Reference Note:__ This configuration option uses the [address common syntax](../prologue/common.md#address). Please
see the [documentation](../prologue/common.md#address) on this format for more information.* see the [documentation](../prologue/common.md#address) on this format for more information.*
Configures the listener address for the Main HTTP Server. The address itself is a listener and the scheme must either be Configures the listener address for the Main HTTP Server. The address itself is a listener and the scheme must either be
the `unix` scheme or one of the `tcp` schemes. the `unix` scheme or one of the `tcp` schemes. It can configure the host, port, and path the listener responds to. If
the path is configured to anything other than `/` Authelia will handle requests for both `/` and the configured path.
__Examples:__ __Examples:__
```yaml ```yaml
server: server:
address: tcp://127.0.0.1:9091 address: tcp://127.0.0.1:9091/
```
```yaml
server:
address: tcp://127.0.0.1:9091/subpath
``` ```
```yaml ```yaml
@ -79,34 +84,6 @@ server:
address: unix:///var/run/authelia.sock address: unix:///var/run/authelia.sock
``` ```
### path
{{< confkey type="string " required="no" >}}
Authelia by default is served from the root `/` location, either via its own domain or subdomain.
Modifying this setting will allow you to serve Authelia out from a specified base path. Please note
that currently only a single level path is supported meaning slashes are not allowed, and only
alphanumeric characters are supported.
__Example:__
```yaml
server:
path: ""
```
*Works for https://auth.example.com/, https://example.com/, etc*.
__Example:__
```yaml
server:
path: authelia
```
*Works for https://auth.example.com/authelia/, https://example.com/authelia/, etc*.
### asset_path ### asset_path
{{< confkey type="string " required="no" >}} {{< confkey type="string " required="no" >}}

View File

@ -88,7 +88,7 @@ Refer to the individual documentation for an option for clarity. In this format
are optional. The default for these when not provided varies. are optional. The default for these when not provided varies.
```text ```text
[<scheme>://]<hostname>[:<port>] [<scheme>://]<hostname>[:<port>][/<path>]
``` ```
##### Port ##### Port
@ -99,7 +99,7 @@ hostname are optional. The default for the scheme when not provided varies, and
available addresses when not provided. available addresses when not provided.
```text ```text
[<scheme>://][hostname]:<port> [<scheme>://][hostname]:<port>[/<path>]
``` ```
##### Unix Domain Socket ##### Unix Domain Socket
@ -131,8 +131,11 @@ Various examples for these formats.
```text ```text
0.0.0.0 0.0.0.0
tcp://0.0.0.0 tcp://0.0.0.0
tcp://0.0.0.0/subpath
tcp://0.0.0.0:9091 tcp://0.0.0.0:9091
tcp://0.0.0.0:9091/subpath
tcp://:9091 tcp://:9091
tcp://:9091/subpath
0.0.0.0:9091 0.0.0.0:9091
udp://0.0.0.0:123 udp://0.0.0.0:123

View File

@ -22,7 +22,7 @@ toc: true
telemetry: telemetry:
metrics: metrics:
enabled: false enabled: false
address: 'tcp://:9959' address: 'tcp://:9959/'
buffers: buffers:
read: 4096 read: 4096
write: 4096 write: 4096
@ -44,7 +44,7 @@ Determines if the [Prometheus] HTTP Metrics Exporter is enabled.
### address ### address
{{< confkey type="address" default="tcp://:9959" required="no" >}} {{< confkey type="address" default="tcp://:9959/" required="no" >}}
*__Reference Note:__ This configuration option uses the [address common syntax](../prologue/common.md#address). Please *__Reference Note:__ This configuration option uses the [address common syntax](../prologue/common.md#address). Please
see the [documentation](../prologue/common.md#address) on this format for more information.* see the [documentation](../prologue/common.md#address) on this format for more information.*

File diff suppressed because one or more lines are too long

View File

@ -47,15 +47,12 @@ default_redirection_url: 'https://home.example.com/'
server: server:
## The address for the Main server to listen on in the address common syntax. ## The address for the Main server to listen on in the address common syntax.
## Formats: ## Formats:
## - [<scheme>://]<hostname>[:<port>] ## - [<scheme>://]<hostname>[:<port>][/<path>]
## - [<scheme>://][hostname]:<port> ## - [<scheme>://][hostname]:<port>[/<path>]
## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'. ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'.
## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9091'. ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9091'.
address: 'tcp://:9091' ## If the path is specified this configures the router to handle both the `/` path and the configured path.
address: 'tcp://:9091/'
## Set the single level path Authelia listens on.
## Must be alphanumeric chars and should not contain any slashes.
path: ''
## Set the path on disk to Authelia assets. ## Set the path on disk to Authelia assets.
## Useful to allow overriding of specific static assets. ## Useful to allow overriding of specific static assets.
@ -162,11 +159,12 @@ telemetry:
## The address for the Metrics server to listen on in the address common syntax. ## The address for the Metrics server to listen on in the address common syntax.
## Formats: ## Formats:
## - [<scheme>://]<hostname>[:<port>] ## - [<scheme>://]<hostname>[:<port>][/<path>]
## - [<scheme>://][hostname]:<port> ## - [<scheme>://][hostname]:<port>[/<path>]
## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'. ## Square brackets indicate optional portions of the format. Scheme must be 'tcp', 'tcp4', 'tcp6', or 'unix'.
## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9959'. ## The default scheme is 'unix' if the address is an absolute path otherwise it's 'tcp'. The default port is '9959'.
address: 'tcp://:9959' ## If the path is not specified it defaults to `/metrics`.
address: 'tcp://:9959/metrics'
## Metrics Server Buffers configuration. ## Metrics Server Buffers configuration.
# buffers: # buffers:

View File

@ -38,6 +38,8 @@ const (
errFmtDecodeHookCouldNotParse = "could not decode '%s' to a %s%s: %w" errFmtDecodeHookCouldNotParse = "could not decode '%s' to a %s%s: %w"
errFmtDecodeHookCouldNotParseBasic = "could not decode to a %s%s: %w" errFmtDecodeHookCouldNotParseBasic = "could not decode to a %s%s: %w"
errFmtDecodeHookCouldNotParseEmptyValue = "could not decode an empty value to a %s%s: %w" errFmtDecodeHookCouldNotParseEmptyValue = "could not decode an empty value to a %s%s: %w"
errFmtSpecialRemappedKey = "configuration key '%s' is deprecated in %s and has been replaced by '%s' when combined with the '%s' in the format of '%s': this should be automatically mapped for you but you will need to adjust your configuration to remove this message"
) )
const ( const (

View File

@ -187,7 +187,7 @@ var deprecations = map[string]Deprecation{
Keep: true, Keep: true,
MapFunc: nil, MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) { ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf("configuration key 'server.host' is deprecated in %s and has been replaced by 'server.address' when combined with the 'server.port' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Version.String())) val.PushWarning(fmt.Errorf("configuration key '%s' is deprecated in %s and has been replaced by '%s' when combined with the 'server.port' and 'server.path' in the format of %s: this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Key, d.Version.String(), d.NewKey, "'[tcp[(4|6)]://]<hostname>[:<port>][/<path>]' or 'tcp[(4|6)://][hostname]:<port>[/<path>]'"))
}, },
}, },
"server.port": { "server.port": {
@ -198,7 +198,18 @@ var deprecations = map[string]Deprecation{
Keep: true, Keep: true,
MapFunc: nil, MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) { ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf("configuration key 'server.port' is deprecated in %s and has been replaced by 'server.address' when combined with the 'server.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Version.String())) val.PushWarning(fmt.Errorf("configuration key '%s' is deprecated in %s and has been replaced by '%s' when combined with the 'server.host' and 'server.path' in the format of %s: this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Key, d.Version.String(), d.NewKey, "'[tcp[(4|6)]://]<hostname>[:<port>][/<path>]' or 'tcp[(4|6)://][hostname]:<port>[/<path>]'"))
},
},
"server.path": {
Version: model.SemanticVersion{Major: 4, Minor: 38},
Key: "server.path",
NewKey: "server.address",
AutoMap: false,
Keep: true,
MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf("configuration key '%s' is deprecated in %s and has been replaced by '%s' when combined with the 'server.host' and 'server.port' in the format of %s: this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Key, d.Version.String(), d.NewKey, "'[tcp[(4|6)]://]<hostname>[:<port>][/<path>]' or 'tcp[(4|6)://][hostname]:<port>[/<path>]'"))
}, },
}, },
"storage.mysql.host": { "storage.mysql.host": {
@ -209,7 +220,7 @@ var deprecations = map[string]Deprecation{
Keep: true, Keep: true,
MapFunc: nil, MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) { ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf("configuration key 'storage.mysql.host' is deprecated in %s and has been replaced by 'storage.mysql.address' when combined with the 'storage.mysql.port' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Version.String())) val.PushWarning(fmt.Errorf(errFmtSpecialRemappedKey, d.Key, d.Version.String(), d.NewKey, "storage.mysql.port", "[tcp://]<hostname>[:<port>]"))
}, },
}, },
"storage.mysql.port": { "storage.mysql.port": {
@ -220,7 +231,7 @@ var deprecations = map[string]Deprecation{
Keep: true, Keep: true,
MapFunc: nil, MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) { ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf("configuration key 'storage.mysql.port' is deprecated in %s and has been replaced by 'storage.mysql.address' when combined with the 'storage.mysql.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Version.String())) val.PushWarning(fmt.Errorf(errFmtSpecialRemappedKey, d.Key, d.Version.String(), d.NewKey, "storage.mysql.host", "[tcp://]<hostname>[:<port>]"))
}, },
}, },
"storage.postgres.host": { "storage.postgres.host": {
@ -231,7 +242,7 @@ var deprecations = map[string]Deprecation{
Keep: true, Keep: true,
MapFunc: nil, MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) { ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf("configuration key 'storage.postgres.host' is deprecated in %s and has been replaced by 'storage.postgres.address' when combined with the 'storage.postgres.port' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Version.String())) val.PushWarning(fmt.Errorf(errFmtSpecialRemappedKey, d.Key, d.Version.String(), d.NewKey, "storage.postgres.port", "[tcp://]<hostname>[:<port>]"))
}, },
}, },
"storage.postgres.port": { "storage.postgres.port": {
@ -242,7 +253,29 @@ var deprecations = map[string]Deprecation{
Keep: true, Keep: true,
MapFunc: nil, MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) { ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf("configuration key 'storage.postgres.port' is deprecated in %s and has been replaced by 'storage.postgres.address' when combined with the 'storage.postgres.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message", d.Version.String())) val.PushWarning(fmt.Errorf(errFmtSpecialRemappedKey, d.Key, d.Version.String(), d.NewKey, "storage.postgres.host", "[tcp://]<hostname>[:<port>]"))
},
},
"notifier.smtp.host": {
Version: model.SemanticVersion{Major: 4, Minor: 38},
Key: "notifier.smtp.host",
NewKey: "notifier.smtp.address",
AutoMap: false,
Keep: true,
MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf(errFmtSpecialRemappedKey, d.Key, d.Version.String(), d.NewKey, "notifier.smtp.port", "[tcp://]<hostname>[:<port>]"))
},
},
"notifier.smtp.port": {
Version: model.SemanticVersion{Major: 4, Minor: 38},
Key: "notifier.smtp.port",
NewKey: "notifier.smtp.address",
AutoMap: false,
Keep: true,
MapFunc: nil,
ErrFunc: func(d Deprecation, _ map[string]any, _ any, val *schema.StructValidator) {
val.PushWarning(fmt.Errorf(errFmtSpecialRemappedKey, d.Key, d.Version.String(), d.NewKey, "notifier.smtp.host", "[tcp://]<hostname>[:<port>]"))
}, },
}, },
"authentication_backend.ldap.url": { "authentication_backend.ldap.url": {

View File

@ -314,44 +314,24 @@ func TestShouldValidateDeprecatedEnvNamesWithDeprecatedKeys(t *testing.T) {
assert.Len(t, val.Errors(), 0) assert.Len(t, val.Errors(), 0)
warnings := val.Warnings() warnings := val.Warnings()
require.Len(t, warnings, 3) require.Len(t, warnings, 10)
sort.Sort(utils.ErrSliceSortAlphabetical(warnings)) sort.Sort(utils.ErrSliceSortAlphabetical(warnings))
assert.EqualError(t, warnings[0], "configuration key 'authentication_backend.ldap.url' is deprecated in 4.38.0 and has been replaced by 'authentication_backend.ldap.address': this has been automatically mapped for you but you will need to adjust your configuration to remove this message") assert.EqualError(t, warnings[0], "configuration key 'authentication_backend.ldap.url' is deprecated in 4.38.0 and has been replaced by 'authentication_backend.ldap.address': this has been automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[1], "configuration key 'storage.mysql.host' is deprecated in 4.38.0 and has been replaced by 'storage.mysql.address' when combined with the 'storage.mysql.port' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message") assert.EqualError(t, warnings[1], "configuration key 'notifier.smtp.host' is deprecated in 4.38.0 and has been replaced by 'notifier.smtp.address' when combined with the 'notifier.smtp.port' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[2], "configuration key 'storage.mysql.port' is deprecated in 4.38.0 and has been replaced by 'storage.mysql.address' when combined with the 'storage.mysql.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message") assert.EqualError(t, warnings[2], "configuration key 'notifier.smtp.port' is deprecated in 4.38.0 and has been replaced by 'notifier.smtp.address' when combined with the 'notifier.smtp.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[3], "configuration key 'server.host' is deprecated in 4.38.0 and has been replaced by 'server.address' when combined with the 'server.port' and 'server.path' in the format of '[tcp[(4|6)]://]<hostname>[:<port>][/<path>]' or 'tcp[(4|6)://][hostname]:<port>[/<path>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[4], "configuration key 'server.path' is deprecated in 4.38.0 and has been replaced by 'server.address' when combined with the 'server.host' and 'server.port' in the format of '[tcp[(4|6)]://]<hostname>[:<port>][/<path>]' or 'tcp[(4|6)://][hostname]:<port>[/<path>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[5], "configuration key 'server.port' is deprecated in 4.38.0 and has been replaced by 'server.address' when combined with the 'server.host' and 'server.path' in the format of '[tcp[(4|6)]://]<hostname>[:<port>][/<path>]' or 'tcp[(4|6)://][hostname]:<port>[/<path>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[6], "configuration key 'storage.mysql.host' is deprecated in 4.38.0 and has been replaced by 'storage.mysql.address' when combined with the 'storage.mysql.port' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[7], "configuration key 'storage.mysql.port' is deprecated in 4.38.0 and has been replaced by 'storage.mysql.address' when combined with the 'storage.mysql.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[8], "configuration key 'storage.postgres.host' is deprecated in 4.38.0 and has been replaced by 'storage.postgres.address' when combined with the 'storage.postgres.port' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[9], "configuration key 'storage.postgres.port' is deprecated in 4.38.0 and has been replaced by 'storage.postgres.address' when combined with the 'storage.postgres.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.Equal(t, "ldap://from-env:389", c.AuthenticationBackend.LDAP.Address.String()) assert.Equal(t, "ldap://from-env:389", c.AuthenticationBackend.LDAP.Address.String())
} }
func TestShouldValidateDeprecatedEnvNamesWithDeprecatedKeysAlt(t *testing.T) {
val := schema.NewStructValidator()
keys, c, err := Load(val, NewDefaultSources([]string{"./test_resources/config.deprecated.alt.yml"}, DefaultEnvPrefix, DefaultEnvDelimiter)...)
assert.NoError(t, err)
validator.ValidateKeys(keys, DefaultEnvPrefix, val)
assert.Len(t, val.Errors(), 0)
warnings := val.Warnings()
require.Len(t, warnings, 3)
sort.Sort(utils.ErrSliceSortAlphabetical(warnings))
assert.EqualError(t, warnings[0], "configuration key 'authentication_backend.ldap.url' is deprecated in 4.38.0 and has been replaced by 'authentication_backend.ldap.address': this has been automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[1], "configuration key 'storage.postgres.host' is deprecated in 4.38.0 and has been replaced by 'storage.postgres.address' when combined with the 'storage.postgres.port' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
assert.EqualError(t, warnings[2], "configuration key 'storage.postgres.port' is deprecated in 4.38.0 and has been replaced by 'storage.postgres.address' when combined with the 'storage.postgres.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
val.Clear()
validator.ValidateConfiguration(c, val)
require.NotNil(t, c.Storage.PostgreSQL.Address)
assert.Equal(t, "tcp://127.0.0.1:5432", c.Storage.PostgreSQL.Address.String())
}
func TestShouldRaiseErrOnInvalidNotifierSMTPSender(t *testing.T) { func TestShouldRaiseErrOnInvalidNotifierSMTPSender(t *testing.T) {
val := schema.NewStructValidator() val := schema.NewStructValidator()
keys, _, err := Load(val, NewDefaultSources([]string{"./test_resources/config_smtp_sender_invalid.yml"}, DefaultEnvPrefix, DefaultEnvDelimiter)...) keys, _, err := Load(val, NewDefaultSources([]string{"./test_resources/config_smtp_sender_invalid.yml"}, DefaultEnvPrefix, DefaultEnvDelimiter)...)
@ -495,7 +475,7 @@ func TestShouldLoadDirectoryConfiguration(t *testing.T) {
assert.Len(t, val.Errors(), 0) assert.Len(t, val.Errors(), 0)
require.Len(t, val.Warnings(), 1) require.Len(t, val.Warnings(), 1)
assert.EqualError(t, val.Warnings()[0], "configuration key 'server.port' is deprecated in 4.38.0 and has been replaced by 'server.address' when combined with the 'server.host' in the format of '[tcp://]<hostname>[:<port>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message") assert.EqualError(t, val.Warnings()[0], "configuration key 'server.port' is deprecated in 4.38.0 and has been replaced by 'server.address' when combined with the 'server.host' and 'server.path' in the format of '[tcp[(4|6)]://]<hostname>[:<port>][/<path>]' or 'tcp[(4|6)://][hostname]:<port>[/<path>]': this should be automatically mapped for you but you will need to adjust your configuration to remove this message")
} }
func testSetEnv(t *testing.T, key, value string) { func testSetEnv(t *testing.T, key, value string) {

View File

@ -259,7 +259,6 @@ var Keys = []string{
"notifier.smtp.port", "notifier.smtp.port",
"notifier.template_path", "notifier.template_path",
"server.address", "server.address",
"server.path",
"server.asset_path", "server.asset_path",
"server.disable_healthcheck", "server.disable_healthcheck",
"server.tls.certificate", "server.tls.certificate",
@ -279,6 +278,7 @@ var Keys = []string{
"server.timeouts.idle", "server.timeouts.idle",
"server.host", "server.host",
"server.port", "server.port",
"server.path",
"telemetry.metrics.enabled", "telemetry.metrics.enabled",
"telemetry.metrics.address", "telemetry.metrics.address",
"telemetry.metrics.buffers.read", "telemetry.metrics.buffers.read",

View File

@ -8,7 +8,6 @@ import (
// ServerConfiguration represents the configuration of the http server. // ServerConfiguration represents the configuration of the http server.
type ServerConfiguration struct { type ServerConfiguration struct {
Address *AddressTCP `koanf:"address"` Address *AddressTCP `koanf:"address"`
Path string `koanf:"path"`
AssetPath string `koanf:"asset_path"` AssetPath string `koanf:"asset_path"`
DisableHealthcheck bool `koanf:"disable_healthcheck"` DisableHealthcheck bool `koanf:"disable_healthcheck"`
@ -24,6 +23,9 @@ type ServerConfiguration struct {
// Deprecated: use address instead. // Deprecated: use address instead.
Port int `koanf:"port"` Port int `koanf:"port"`
// Deprecated: use address instead.
Path string `koanf:"path"`
} }
// ServerEndpoints is the endpoints configuration for the HTTP server. // ServerEndpoints is the endpoints configuration for the HTTP server.
@ -60,7 +62,7 @@ type ServerHeaders struct {
// DefaultServerConfiguration represents the default values of the ServerConfiguration. // DefaultServerConfiguration represents the default values of the ServerConfiguration.
var DefaultServerConfiguration = ServerConfiguration{ var DefaultServerConfiguration = ServerConfiguration{
Address: &AddressTCP{Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: ":9091"}}}, Address: &AddressTCP{Address{true, false, -1, 9091, &url.URL{Scheme: AddressSchemeTCP, Host: ":9091", Path: "/"}}},
Buffers: ServerBuffers{ Buffers: ServerBuffers{
Read: 4096, Read: 4096,
Write: 4096, Write: 4096,

View File

@ -21,7 +21,7 @@ type TelemetryMetricsConfig struct {
// DefaultTelemetryConfig is the default telemetry configuration. // DefaultTelemetryConfig is the default telemetry configuration.
var DefaultTelemetryConfig = TelemetryConfig{ var DefaultTelemetryConfig = TelemetryConfig{
Metrics: TelemetryMetricsConfig{ Metrics: TelemetryMetricsConfig{
Address: &AddressTCP{Address{true, false, -1, 9959, &url.URL{Scheme: AddressSchemeTCP, Host: ":9959"}}}, Address: &AddressTCP{Address{true, false, -1, 9959, &url.URL{Scheme: AddressSchemeTCP, Host: ":9959", Path: "/metrics"}}},
Buffers: ServerBuffers{ Buffers: ServerBuffers{
Read: 4096, Read: 4096,
Write: 4096, Write: 4096,

View File

@ -336,6 +336,15 @@ func (a *Address) Path() string {
return a.url.Path return a.url.Path
} }
// SetPath sets the path.
func (a *Address) SetPath(path string) {
if !a.valid || a.url == nil {
return
}
a.url.Path = path
}
// SocketHostname returns the correct hostname for a socket connection. // SocketHostname returns the correct hostname for a socket connection.
func (a *Address) SocketHostname() string { func (a *Address) SocketHostname() string {
if !a.valid || a.url == nil { if !a.valid || a.url == nil {

View File

@ -1,173 +0,0 @@
---
default_redirection_url: https://home.example.com:8080/
server:
address: "tcp://127.0.0.1:9091"
endpoints:
authz:
forward-auth:
implementation: ForwardAuth
authn_strategies:
- name: HeaderProxyAuthorization
- name: CookieSession
ext-authz:
implementation: ExtAuthz
authn_strategies:
- name: HeaderProxyAuthorization
- name: CookieSession
auth-request:
implementation: AuthRequest
authn_strategies:
- name: HeaderAuthRequestProxyAuthorization
- name: CookieSession
legacy:
implementation: Legacy
log:
level: debug
totp:
issuer: authelia.com
duo_api:
hostname: api-123456789.example.com
integration_key: ABCDEF
authentication_backend:
ldap:
url: 'ldap://127.0.0.1'
tls:
private_key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA6z1LOg1ZCqb0lytXWZ+MRBpMHEXOoTOLYgfZXt1IYyE3Z758
cyalk0NYQhY5cZDsXPYWPvAHiPMUxutWkoxFwby56S+AbIMa3/Is+ILrHRJs8Exn
ZkpyrYFxPX12app2kErdmAkHSx0Z5/kuXiz96PHs8S8/ZbyZolLHzdfLtSzjvRm5
Zue5iFzsf19NJz5CIBfv8g5lRwtE8wNJoRSpn1xq7fqfuA0weDNFPzjlNWRLy6aa
rK7qJexRkmkCs4sLgyl+9NODYJpvmN8E1yhyC27E0joI6rBFVW7Ihv+cSPCdDzGp
EWe81x3AeqAa3mjVqkiq4u4Z2i8JDgBaPboqJwIDAQABAoIBAAFdLZ58jVOefDSU
L8F5R1rtvBs93GDa56f926jNJ6pLewLC+/2+757W+SAI+PRLntM7Kg3bXm/Q2QH+
Q1Y+MflZmspbWCdI61L5GIGoYKyeers59i+FpvySj5GHtLQRiTZ0+Kv1AXHSDWBm
9XneUOqU3IbZe0ifu1RRno72/VtjkGXbW8Mkkw+ohyGbIeTx/0/JQ6sSNZTT3Vk7
8i4IXptq3HSF0/vqZuah8rShoeNq72pD1YLM9YPdL5by1QkDLnqATDiCpLBTCaNV
I8sqYEun+HYbQzBj8ZACG2JVZpEEidONWQHw5BPWO95DSZYrVnEkuCqeH+u5vYt7
CHuJ3AECgYEA+W3v5z+j91w1VPHS0VB3SCDMouycAMIUnJPAbt+0LPP0scUFsBGE
hPAKddC54pmMZRQ2KIwBKiyWfCrJ8Xz8Yogn7fJgmwTHidJBr2WQpIEkNGlK3Dzi
jXL2sh0yC7sHvn0DqiQ79l/e7yRbSnv2wrTJEczOOH2haD7/tBRyCYECgYEA8W+q
E9YyGvEltnPFaOxofNZ8LHVcZSsQI5b6fc0iE7fjxFqeXPXEwGSOTwqQLQRiHn9b
CfPmIG4Vhyq0otVmlPvUnfBZ2OK+tl5X2/mQFO3ROMdvpi0KYa994uqfJdSTaqLn
jjoKFB906UFHnDQDLZUNiV1WwnkTglgLc+xrd6cCgYEAqqthyv6NyBTM3Tm2gcio
Ra9Dtntl51LlXZnvwy3IkDXBCd6BHM9vuLKyxZiziGx+Vy90O1xI872cnot8sINQ
Am+dur/tAEVN72zxyv0Y8qb2yfH96iKy9gxi5s75TnOEQgAygLnYWaWR2lorKRUX
bHTdXBOiS58S0UzCFEslGIECgYBqkO4SKWYeTDhoKvuEj2yjRYyzlu28XeCWxOo1
otiauX0YSyNBRt2cSgYiTzhKFng0m+QUJYp63/wymB/5C5Zmxi0XtWIDADpLhqLj
HmmBQ2Mo26alQ5YkffBju0mZyhVzaQop1eZi8WuKFV1FThPlB7hc3E0SM5zv2Grd
tQnOWwKBgQC40yZY0PcjuILhy+sIc0Wvh7LUA7taSdTye149kRvbvsCDN7Jh75lM
USjhLXY0Nld2zBm9r8wMb81mXH29uvD+tDqqsICvyuKlA/tyzXR+QTr7dCVKVwu0
1YjCJ36UpTsLre2f8nOSLtNmRfDPtbOE2mkOoO9dD9UU0XZwnvn9xw==
-----END RSA PRIVATE KEY-----
base_dn: dc=example,dc=com
username_attribute: uid
additional_users_dn: ou=users
users_filter: (&({username_attribute}={input})(objectCategory=person)(objectClass=user))
additional_groups_dn: ou=groups
groups_filter: (&(member={dn})(objectClass=groupOfNames))
group_name_attribute: cn
mail_attribute: mail
user: cn=admin,dc=example,dc=com
access_control:
default_policy: deny
rules:
# Rules applied to everyone
- domain: public.example.com
policy: bypass
- domain: secure.example.com
policy: one_factor
# Network based rule, if not provided any network matches.
networks:
- 192.168.1.0/24
- domain: secure.example.com
policy: two_factor
- domain: [singlefactor.example.com, onefactor.example.com]
policy: one_factor
# Rules applied to 'admins' group
- domain: "mx2.mail.example.com"
subject: "group:admins"
policy: deny
- domain: "*.example.com"
subject: "group:admins"
policy: two_factor
# Rules applied to 'dev' group
- domain: dev.example.com
resources:
- "^/groups/dev/.*$"
subject: "group:dev"
policy: two_factor
# Rules applied to user 'john'
- domain: dev.example.com
resources:
- "^/users/john/.*$"
subject: "user:john"
policy: two_factor
# Rules applied to 'dev' group and user 'john'
- domain: dev.example.com
resources:
- "^/deny-all.*$"
subject: ["group:dev", "user:john"]
policy: deny
# Rules applied to user 'harry'
- domain: dev.example.com
resources:
- "^/users/harry/.*$"
subject: "user:harry"
policy: two_factor
# Rules applied to user 'bob'
- domain: "*.mail.example.com"
subject: "user:bob"
policy: two_factor
- domain: "dev.example.com"
resources:
- "^/users/bob/.*$"
subject: "user:bob"
policy: two_factor
session:
name: authelia_session
expiration: 3600000 # 1 hour
inactivity: 300000 # 5 minutes
domain: example.com
redis:
host: 127.0.0.1
port: 6379
high_availability:
sentinel_name: test
regulation:
max_retries: 3
find_time: 120
ban_time: 300
storage:
postgres:
host: 127.0.0.1
port: 5432
database: authelia
username: authelia
notifier:
smtp:
username: test
host: 127.0.0.1
port: 1025
sender: admin@example.com
disable_require_tls: true
...

View File

@ -1,173 +1,23 @@
--- ---
default_redirection_url: https://home.example.com:8080/
server: server:
address: "tcp://127.0.0.1:9091" host: '0.0.0.0'
endpoints: port: 9091
authz: path: "auth"
forward-auth:
implementation: ForwardAuth
authn_strategies:
- name: HeaderProxyAuthorization
- name: CookieSession
ext-authz:
implementation: ExtAuthz
authn_strategies:
- name: HeaderProxyAuthorization
- name: CookieSession
auth-request:
implementation: AuthRequest
authn_strategies:
- name: HeaderAuthRequestProxyAuthorization
- name: CookieSession
legacy:
implementation: Legacy
log:
level: debug
totp:
issuer: authelia.com
duo_api:
hostname: api-123456789.example.com
integration_key: ABCDEF
authentication_backend: authentication_backend:
ldap: ldap:
url: 'ldap://127.0.0.1' url: 'ldap://127.0.0.1'
tls:
private_key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA6z1LOg1ZCqb0lytXWZ+MRBpMHEXOoTOLYgfZXt1IYyE3Z758
cyalk0NYQhY5cZDsXPYWPvAHiPMUxutWkoxFwby56S+AbIMa3/Is+ILrHRJs8Exn
ZkpyrYFxPX12app2kErdmAkHSx0Z5/kuXiz96PHs8S8/ZbyZolLHzdfLtSzjvRm5
Zue5iFzsf19NJz5CIBfv8g5lRwtE8wNJoRSpn1xq7fqfuA0weDNFPzjlNWRLy6aa
rK7qJexRkmkCs4sLgyl+9NODYJpvmN8E1yhyC27E0joI6rBFVW7Ihv+cSPCdDzGp
EWe81x3AeqAa3mjVqkiq4u4Z2i8JDgBaPboqJwIDAQABAoIBAAFdLZ58jVOefDSU
L8F5R1rtvBs93GDa56f926jNJ6pLewLC+/2+757W+SAI+PRLntM7Kg3bXm/Q2QH+
Q1Y+MflZmspbWCdI61L5GIGoYKyeers59i+FpvySj5GHtLQRiTZ0+Kv1AXHSDWBm
9XneUOqU3IbZe0ifu1RRno72/VtjkGXbW8Mkkw+ohyGbIeTx/0/JQ6sSNZTT3Vk7
8i4IXptq3HSF0/vqZuah8rShoeNq72pD1YLM9YPdL5by1QkDLnqATDiCpLBTCaNV
I8sqYEun+HYbQzBj8ZACG2JVZpEEidONWQHw5BPWO95DSZYrVnEkuCqeH+u5vYt7
CHuJ3AECgYEA+W3v5z+j91w1VPHS0VB3SCDMouycAMIUnJPAbt+0LPP0scUFsBGE
hPAKddC54pmMZRQ2KIwBKiyWfCrJ8Xz8Yogn7fJgmwTHidJBr2WQpIEkNGlK3Dzi
jXL2sh0yC7sHvn0DqiQ79l/e7yRbSnv2wrTJEczOOH2haD7/tBRyCYECgYEA8W+q
E9YyGvEltnPFaOxofNZ8LHVcZSsQI5b6fc0iE7fjxFqeXPXEwGSOTwqQLQRiHn9b
CfPmIG4Vhyq0otVmlPvUnfBZ2OK+tl5X2/mQFO3ROMdvpi0KYa994uqfJdSTaqLn
jjoKFB906UFHnDQDLZUNiV1WwnkTglgLc+xrd6cCgYEAqqthyv6NyBTM3Tm2gcio
Ra9Dtntl51LlXZnvwy3IkDXBCd6BHM9vuLKyxZiziGx+Vy90O1xI872cnot8sINQ
Am+dur/tAEVN72zxyv0Y8qb2yfH96iKy9gxi5s75TnOEQgAygLnYWaWR2lorKRUX
bHTdXBOiS58S0UzCFEslGIECgYBqkO4SKWYeTDhoKvuEj2yjRYyzlu28XeCWxOo1
otiauX0YSyNBRt2cSgYiTzhKFng0m+QUJYp63/wymB/5C5Zmxi0XtWIDADpLhqLj
HmmBQ2Mo26alQ5YkffBju0mZyhVzaQop1eZi8WuKFV1FThPlB7hc3E0SM5zv2Grd
tQnOWwKBgQC40yZY0PcjuILhy+sIc0Wvh7LUA7taSdTye149kRvbvsCDN7Jh75lM
USjhLXY0Nld2zBm9r8wMb81mXH29uvD+tDqqsICvyuKlA/tyzXR+QTr7dCVKVwu0
1YjCJ36UpTsLre2f8nOSLtNmRfDPtbOE2mkOoO9dD9UU0XZwnvn9xw==
-----END RSA PRIVATE KEY-----
base_dn: dc=example,dc=com
username_attribute: uid
additional_users_dn: ou=users
users_filter: (&({username_attribute}={input})(objectCategory=person)(objectClass=user))
additional_groups_dn: ou=groups
groups_filter: (&(member={dn})(objectClass=groupOfNames))
group_name_attribute: cn
mail_attribute: mail
user: cn=admin,dc=example,dc=com
access_control:
default_policy: deny
rules:
# Rules applied to everyone
- domain: public.example.com
policy: bypass
- domain: secure.example.com
policy: one_factor
# Network based rule, if not provided any network matches.
networks:
- 192.168.1.0/24
- domain: secure.example.com
policy: two_factor
- domain: [singlefactor.example.com, onefactor.example.com]
policy: one_factor
# Rules applied to 'admins' group
- domain: "mx2.mail.example.com"
subject: "group:admins"
policy: deny
- domain: "*.example.com"
subject: "group:admins"
policy: two_factor
# Rules applied to 'dev' group
- domain: dev.example.com
resources:
- "^/groups/dev/.*$"
subject: "group:dev"
policy: two_factor
# Rules applied to user 'john'
- domain: dev.example.com
resources:
- "^/users/john/.*$"
subject: "user:john"
policy: two_factor
# Rules applied to 'dev' group and user 'john'
- domain: dev.example.com
resources:
- "^/deny-all.*$"
subject: ["group:dev", "user:john"]
policy: deny
# Rules applied to user 'harry'
- domain: dev.example.com
resources:
- "^/users/harry/.*$"
subject: "user:harry"
policy: two_factor
# Rules applied to user 'bob'
- domain: "*.mail.example.com"
subject: "user:bob"
policy: two_factor
- domain: "dev.example.com"
resources:
- "^/users/bob/.*$"
subject: "user:bob"
policy: two_factor
session:
name: authelia_session
expiration: 3600000 # 1 hour
inactivity: 300000 # 5 minutes
domain: example.com
redis:
host: 127.0.0.1
port: 6379
high_availability:
sentinel_name: test
regulation:
max_retries: 3
find_time: 120
ban_time: 300
storage: storage:
mysql: mysql:
host: 127.0.0.1 host: 127.0.0.1
port: 3306 port: 3306
database: authelia postgres:
username: authelia host: 127.0.0.1
port: 5432
notifier: notifier:
smtp: smtp:
username: test
host: 127.0.0.1 host: 127.0.0.1
port: 1025 port: 1025
sender: admin@example.com
disable_require_tls: true
... ...

View File

@ -323,8 +323,9 @@ const (
errFmtServerAddressLegacyAndModern = "server: option 'host' and 'port' can't be configured at the same time as 'address'" errFmtServerAddressLegacyAndModern = "server: option 'host' and 'port' can't be configured at the same time as 'address'"
errFmtServerAddress = "server: option 'address' with value '%s' is invalid: %w" errFmtServerAddress = "server: option 'address' with value '%s' is invalid: %w"
errFmtServerPathNoForwardSlashes = "server: option 'path' must not contain any forward slashes" errFmtServerPathNoForwardSlashes = "server: option 'path' must not contain any forward slashes"
errFmtServerPathAlphaNum = "server: option 'path' must only contain alpha numeric characters" errFmtServerPathNotEndForwardSlash = "server: option 'address' must not and with a forward slash but it's configured as '%s'"
errFmtServerPathAlphaNum = "server: option 'path' must only contain alpha numeric characters"
errFmtServerEndpointsAuthzImplementation = "server: endpoints: authz: %s: option 'implementation' must be one of %s but it's configured as '%s'" errFmtServerEndpointsAuthzImplementation = "server: endpoints: authz: %s: option 'implementation' must be one of %s but it's configured as '%s'"
errFmtServerEndpointsAuthzStrategy = "server: endpoints: authz: %s: authn_strategies: option 'name' must be one of %s but it's configured as '%s'" errFmtServerEndpointsAuthzStrategy = "server: endpoints: authz: %s: authn_strategies: option 'name' must be one of %s but it's configured as '%s'"

View File

@ -59,17 +59,6 @@ func ValidateServer(config *schema.Configuration, validator *schema.StructValida
ValidateServerAddress(config, validator) ValidateServerAddress(config, validator)
ValidateServerTLS(config, validator) ValidateServerTLS(config, validator)
switch {
case strings.Contains(config.Server.Path, "/"):
validator.Push(fmt.Errorf(errFmtServerPathNoForwardSlashes))
case !utils.IsStringAlphaNumeric(config.Server.Path):
validator.Push(fmt.Errorf(errFmtServerPathAlphaNum))
case config.Server.Path == "": // Don't do anything if it's blank.
break
default:
config.Server.Path = path.Clean("/" + config.Server.Path)
}
if config.Server.Buffers.Read <= 0 { if config.Server.Buffers.Read <= 0 {
config.Server.Buffers.Read = schema.DefaultServerConfiguration.Buffers.Read config.Server.Buffers.Read = schema.DefaultServerConfiguration.Buffers.Read
} }
@ -96,11 +85,12 @@ func ValidateServer(config *schema.Configuration, validator *schema.StructValida
// ValidateServerAddress checks the configured server address is correct. // ValidateServerAddress checks the configured server address is correct.
func ValidateServerAddress(config *schema.Configuration, validator *schema.StructValidator) { func ValidateServerAddress(config *schema.Configuration, validator *schema.StructValidator) {
if config.Server.Address == nil { if config.Server.Address == nil {
if config.Server.Host == "" && config.Server.Port == 0 { //nolint:staticcheck if config.Server.Host == "" && config.Server.Port == 0 && config.Server.Path == "" { //nolint:staticcheck
config.Server.Address = schema.DefaultServerConfiguration.Address config.Server.Address = schema.DefaultServerConfiguration.Address
} else { } else {
host := config.Server.Host //nolint:staticcheck host := config.Server.Host //nolint:staticcheck
port := config.Server.Port //nolint:staticcheck port := config.Server.Port //nolint:staticcheck
subpath := config.Server.Path //nolint:staticcheck
if host == "" { if host == "" {
host = schema.DefaultServerConfiguration.Address.Hostname() host = schema.DefaultServerConfiguration.Address.Hostname()
@ -110,7 +100,20 @@ func ValidateServerAddress(config *schema.Configuration, validator *schema.Struc
port = schema.DefaultServerConfiguration.Address.Port() port = schema.DefaultServerConfiguration.Address.Port()
} }
switch {
case strings.Contains(subpath, "/"):
validator.Push(fmt.Errorf(errFmtServerPathNoForwardSlashes))
case !utils.IsStringAlphaNumeric(config.Server.Path): //nolint:staticcheck
validator.Push(fmt.Errorf(errFmtServerPathAlphaNum))
case subpath == "":
subpath = schema.DefaultServerConfiguration.Address.Path()
default:
subpath = path.Clean("/" + config.Server.Path) //nolint:staticcheck
}
config.Server.Address = &schema.AddressTCP{Address: schema.NewAddressFromNetworkValues(schema.AddressSchemeTCP, host, port)} config.Server.Address = &schema.AddressTCP{Address: schema.NewAddressFromNetworkValues(schema.AddressSchemeTCP, host, port)}
config.Server.Address.SetPath(subpath)
} }
} else { } else {
if config.Server.Host != "" || config.Server.Port != 0 { //nolint:staticcheck if config.Server.Host != "" || config.Server.Port != 0 { //nolint:staticcheck
@ -123,6 +126,10 @@ func ValidateServerAddress(config *schema.Configuration, validator *schema.Struc
validator.Push(fmt.Errorf(errFmtServerAddress, config.Server.Address.String(), err)) validator.Push(fmt.Errorf(errFmtServerAddress, config.Server.Address.String(), err))
} }
} }
if path := config.Server.Address.Path(); path != "/" && strings.HasSuffix(path, "/") {
validator.Push(fmt.Errorf(errFmtServerPathNotEndForwardSlash, path))
}
} }
// ValidateServerEndpoints configures the default endpoints and checks the configuration of custom endpoints. // ValidateServerEndpoints configures the default endpoints and checks the configuration of custom endpoints.

View File

@ -23,66 +23,97 @@ func TestShouldSetDefaultServerValues(t *testing.T) {
assert.Len(t, validator.Errors(), 0) assert.Len(t, validator.Errors(), 0)
assert.Len(t, validator.Warnings(), 0) assert.Len(t, validator.Warnings(), 0)
assert.Equal(t, "", config.Server.Host) //nolint:staticcheck
assert.Equal(t, 0, config.Server.Port) //nolint:staticcheck
assert.Equal(t, schema.DefaultServerConfiguration.Address, config.Server.Address) assert.Equal(t, schema.DefaultServerConfiguration.Address, config.Server.Address)
assert.Equal(t, schema.DefaultServerConfiguration.Buffers.Read, config.Server.Buffers.Read) assert.Equal(t, schema.DefaultServerConfiguration.Buffers.Read, config.Server.Buffers.Read)
assert.Equal(t, schema.DefaultServerConfiguration.Buffers.Write, config.Server.Buffers.Write) assert.Equal(t, schema.DefaultServerConfiguration.Buffers.Write, config.Server.Buffers.Write)
assert.Equal(t, schema.DefaultServerConfiguration.TLS.Key, config.Server.TLS.Key) assert.Equal(t, schema.DefaultServerConfiguration.TLS.Key, config.Server.TLS.Key)
assert.Equal(t, schema.DefaultServerConfiguration.TLS.Certificate, config.Server.TLS.Certificate) assert.Equal(t, schema.DefaultServerConfiguration.TLS.Certificate, config.Server.TLS.Certificate)
assert.Equal(t, schema.DefaultServerConfiguration.Path, config.Server.Path)
assert.Equal(t, schema.DefaultServerConfiguration.Endpoints.EnableExpvars, config.Server.Endpoints.EnableExpvars) assert.Equal(t, schema.DefaultServerConfiguration.Endpoints.EnableExpvars, config.Server.Endpoints.EnableExpvars)
assert.Equal(t, schema.DefaultServerConfiguration.Endpoints.EnablePprof, config.Server.Endpoints.EnablePprof) assert.Equal(t, schema.DefaultServerConfiguration.Endpoints.EnablePprof, config.Server.Endpoints.EnablePprof)
assert.Equal(t, schema.DefaultServerConfiguration.Endpoints.Authz, config.Server.Endpoints.Authz) assert.Equal(t, schema.DefaultServerConfiguration.Endpoints.Authz, config.Server.Endpoints.Authz)
assert.Equal(t, "", config.Server.Host) //nolint:staticcheck
assert.Equal(t, 0, config.Server.Port) //nolint:staticcheck
assert.Equal(t, "", config.Server.Path) //nolint:staticcheck
} }
func TestShouldSetDefaultServerValuesWithLegacyAddress(t *testing.T) { func TestShouldSetDefaultServerValuesWithLegacyAddress(t *testing.T) {
validator := schema.NewStructValidator() testCases := []struct {
config := &schema.Configuration{ name string
Server: schema.ServerConfiguration{ have schema.ServerConfiguration
Host: "abc", expected schema.Address
Port: 123, }{
{
"ShouldParseAll",
schema.ServerConfiguration{
Host: "abc",
Port: 123,
Path: "subpath",
},
MustParseAddress("tcp://abc:123/subpath"),
},
{
"ShouldParseHostAndPort",
schema.ServerConfiguration{
Host: "abc",
Port: 123,
},
MustParseAddress("tcp://abc:123/"),
},
{
"ShouldParseHostAndPath",
schema.ServerConfiguration{
Host: "abc",
Path: "subpath",
},
MustParseAddress("tcp://abc:9091/subpath"),
},
{
"ShouldParsePortAndPath",
schema.ServerConfiguration{
Port: 123,
Path: "subpath",
},
MustParseAddress("tcp://:123/subpath"),
},
{
"ShouldParseHost",
schema.ServerConfiguration{
Host: "abc",
},
MustParseAddress("tcp://abc:9091/"),
},
{
"ShouldParsePort",
schema.ServerConfiguration{
Port: 123,
},
MustParseAddress("tcp://:123/"),
},
{
"ShouldParsePath",
schema.ServerConfiguration{
Path: "subpath",
},
MustParseAddress("tcp://:9091/subpath"),
}, },
} }
ValidateServer(config, validator) for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
validator := schema.NewStructValidator()
config := &schema.Configuration{
Server: tc.have,
}
assert.Len(t, validator.Errors(), 0) ValidateServer(config, validator)
assert.Len(t, validator.Warnings(), 0)
assert.Equal(t, "abc", config.Server.Host) //nolint:staticcheck assert.Len(t, validator.Errors(), 0)
assert.Equal(t, 123, config.Server.Port) //nolint:staticcheck assert.Len(t, validator.Warnings(), 0)
assert.Equal(t, &schema.AddressTCP{Address: MustParseAddress("tcp://abc:123")}, config.Server.Address)
config = &schema.Configuration{ assert.Equal(t, &schema.AddressTCP{Address: tc.expected}, config.Server.Address)
Server: schema.ServerConfiguration{ })
Host: "abc",
},
} }
ValidateServer(config, validator)
assert.Len(t, validator.Errors(), 0)
assert.Len(t, validator.Warnings(), 0)
assert.Equal(t, "abc", config.Server.Host) //nolint:staticcheck
assert.Equal(t, 0, config.Server.Port) //nolint:staticcheck
assert.Equal(t, &schema.AddressTCP{Address: MustParseAddress("tcp://abc:9091")}, config.Server.Address)
config = &schema.Configuration{
Server: schema.ServerConfiguration{
Port: 123,
},
}
ValidateServer(config, validator)
assert.Len(t, validator.Errors(), 0)
assert.Len(t, validator.Warnings(), 0)
assert.Equal(t, "", config.Server.Host) //nolint:staticcheck
assert.Equal(t, 123, config.Server.Port) //nolint:staticcheck
assert.Equal(t, &schema.AddressTCP{Address: MustParseAddress("tcp://:123")}, config.Server.Address)
} }
func TestShouldSetDefaultConfig(t *testing.T) { func TestShouldSetDefaultConfig(t *testing.T) {
@ -98,20 +129,20 @@ func TestShouldSetDefaultConfig(t *testing.T) {
assert.Equal(t, schema.DefaultServerConfiguration.Buffers.Write, config.Server.Buffers.Write) assert.Equal(t, schema.DefaultServerConfiguration.Buffers.Write, config.Server.Buffers.Write)
} }
func TestShouldParsePathCorrectly(t *testing.T) { func TestValidateSeverAddress(t *testing.T) {
validator := schema.NewStructValidator()
config := &schema.Configuration{ config := &schema.Configuration{
Server: schema.ServerConfiguration{ Server: schema.ServerConfiguration{
Path: "apple", Address: &schema.AddressTCP{Address: MustParseAddress("tcp://:9091/path/")},
}, },
} }
validator := schema.NewStructValidator()
ValidateServer(config, validator) ValidateServer(config, validator)
assert.Len(t, validator.Errors(), 0) require.Len(t, validator.Errors(), 1)
assert.Len(t, validator.Warnings(), 0) assert.Len(t, validator.Warnings(), 0)
assert.Equal(t, "/apple", config.Server.Path) assert.EqualError(t, validator.Errors()[0], "server: option 'address' must not and with a forward slash but it's configured as '/path/'")
} }
func TestValidateServerShouldCorrectlyIdentifyValidAddressSchemes(t *testing.T) { func TestValidateServerShouldCorrectlyIdentifyValidAddressSchemes(t *testing.T) {
@ -236,7 +267,7 @@ func TestShouldValidateAndUpdateAddress(t *testing.T) {
ValidateServer(&config, validator) ValidateServer(&config, validator)
require.Len(t, validator.Errors(), 0) require.Len(t, validator.Errors(), 0)
assert.Equal(t, "tcp://:9091", config.Server.Address.String()) assert.Equal(t, "tcp://:9091/", config.Server.Address.String())
} }
func TestShouldRaiseErrorOnLegacyAndModernValues(t *testing.T) { func TestShouldRaiseErrorOnLegacyAndModernValues(t *testing.T) {
@ -251,22 +282,6 @@ func TestShouldRaiseErrorOnLegacyAndModernValues(t *testing.T) {
assert.EqualError(t, validator.Errors()[0], "server: option 'host' and 'port' can't be configured at the same time as 'address'") assert.EqualError(t, validator.Errors()[0], "server: option 'host' and 'port' can't be configured at the same time as 'address'")
} }
func TestShouldValidateAndUpdateAddressWithOldValues(t *testing.T) {
validator := schema.NewStructValidator()
config := newDefaultConfig()
config.Server.Address = nil
config.Server.Host = local25 //nolint:staticcheck
config.Server.Port = 9999 //nolint:staticcheck
ValidateServer(&config, validator)
assert.Len(t, validator.Errors(), 0)
assert.Len(t, validator.Warnings(), 0)
require.NotNil(t, config.Server.Address)
assert.Equal(t, "tcp://127.0.0.25:9999", config.Server.Address.String())
}
func TestShouldRaiseErrorWhenTLSCertWithoutKeyIsProvided(t *testing.T) { func TestShouldRaiseErrorWhenTLSCertWithoutKeyIsProvided(t *testing.T) {
validator := schema.NewStructValidator() validator := schema.NewStructValidator()
config := newDefaultConfig() config := newDefaultConfig()

View File

@ -20,6 +20,10 @@ func ValidateTelemetry(config *schema.Configuration, validator *schema.StructVal
config.Telemetry.Metrics.Address.SetPort(schema.DefaultTelemetryConfig.Metrics.Address.Port()) config.Telemetry.Metrics.Address.SetPort(schema.DefaultTelemetryConfig.Metrics.Address.Port())
} }
if config.Telemetry.Metrics.Address.Path() == "" {
config.Telemetry.Metrics.Address.SetPath(schema.DefaultTelemetryConfig.Metrics.Address.Path())
}
if config.Telemetry.Metrics.Buffers.Read <= 0 { if config.Telemetry.Metrics.Buffers.Read <= 0 {
config.Telemetry.Metrics.Buffers.Read = schema.DefaultTelemetryConfig.Metrics.Buffers.Read config.Telemetry.Metrics.Buffers.Read = schema.DefaultTelemetryConfig.Metrics.Buffers.Read
} }

View File

@ -38,7 +38,7 @@ func TestValidateTelemetry(t *testing.T) {
&schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("tcp://0.0.0.0")}}}, &schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("tcp://0.0.0.0")}}},
&schema.Configuration{Telemetry: schema.TelemetryConfig{ &schema.Configuration{Telemetry: schema.TelemetryConfig{
Metrics: schema.TelemetryMetricsConfig{ Metrics: schema.TelemetryMetricsConfig{
Address: &schema.AddressTCP{Address: schema.NewAddressFromNetworkValues(schema.AddressSchemeTCP, "0.0.0.0", schema.DefaultTelemetryConfig.Metrics.Address.Port())}, Address: mustParseAddress("tcp://0.0.0.0:9959/metrics"),
Buffers: schema.ServerBuffers{ Buffers: schema.ServerBuffers{
Read: 4096, Read: 4096,
Write: 4096, Write: 4096,
@ -55,7 +55,7 @@ func TestValidateTelemetry(t *testing.T) {
}, },
{ {
"ShouldSetDefaultPortAlt", "ShouldSetDefaultPortAlt",
&schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("tcp://:0")}}}, &schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("tcp://:0/metrics")}}},
&schema.Configuration{Telemetry: schema.DefaultTelemetryConfig}, &schema.Configuration{Telemetry: schema.DefaultTelemetryConfig},
nil, nil,
nil, nil,
@ -63,14 +63,14 @@ func TestValidateTelemetry(t *testing.T) {
{ {
"ShouldSetDefaultPortWithCustomIP", "ShouldSetDefaultPortWithCustomIP",
&schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("tcp://127.0.0.1")}}}, &schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("tcp://127.0.0.1")}}},
&schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("tcp://127.0.0.1:9959")}}}, &schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("tcp://127.0.0.1:9959/metrics")}}},
nil, nil,
nil, nil,
}, },
{ {
"ShouldNotValidateUDP", "ShouldNotValidateUDP",
&schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("udp://0.0.0.0")}}}, &schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("udp://0.0.0.0")}}},
&schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("udp://0.0.0.0:9959")}}}, &schema.Configuration{Telemetry: schema.TelemetryConfig{Metrics: schema.TelemetryMetricsConfig{Address: mustParseAddress("udp://0.0.0.0:9959/metrics")}}},
nil, nil,
[]string{"telemetry: metrics: option 'address' with value 'udp://0.0.0.0:0' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'"}, []string{"telemetry: metrics: option 'address' with value 'udp://0.0.0.0:0' is invalid: scheme must be one of 'tcp', 'tcp4', 'tcp6', or 'unix' but is configured as 'udp'"},
}, },

View File

@ -395,8 +395,8 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers)
r.NotFound = handleNotFound(bridge(serveIndexHandler)) r.NotFound = handleNotFound(bridge(serveIndexHandler))
handler := middlewares.LogRequest(r.Handler) handler := middlewares.LogRequest(r.Handler)
if config.Server.Path != "" { if config.Server.Address.Path() != "/" {
handler = middlewares.StripPath(config.Server.Path)(handler) handler = middlewares.StripPath(config.Server.Address.Path())(handler)
} }
handler = middlewares.Wrap(middlewares.NewMetricsRequest(providers.Metrics), handler) handler = middlewares.Wrap(middlewares.NewMetricsRequest(providers.Metrics), handler)
@ -404,10 +404,10 @@ func handleRouter(config *schema.Configuration, providers middlewares.Providers)
return handler return handler
} }
func handleMetrics() fasthttp.RequestHandler { func handleMetrics(path string) fasthttp.RequestHandler {
r := router.New() r := router.New()
r.GET("/metrics", fasthttpadaptor.NewFastHTTPHandler(promhttp.Handler())) r.GET(path, fasthttpadaptor.NewFastHTTPHandler(promhttp.Handler()))
r.HandleMethodNotAllowed = true r.HandleMethodNotAllowed = true
r.MethodNotAllowed = handlers.Status(fasthttp.StatusMethodNotAllowed) r.MethodNotAllowed = handlers.Status(fasthttp.StatusMethodNotAllowed)

View File

@ -71,14 +71,14 @@ func CreateDefaultServer(config *schema.Configuration, providers middlewares.Pro
} }
if err = writeHealthCheckEnv(config.Server.DisableHealthcheck, connectionScheme, config.Server.Address.Hostname(), if err = writeHealthCheckEnv(config.Server.DisableHealthcheck, connectionScheme, config.Server.Address.Hostname(),
config.Server.Path, config.Server.Address.Port()); err != nil { config.Server.Address.Path(), config.Server.Address.Port()); err != nil {
return nil, nil, nil, false, fmt.Errorf("unable to configure healthcheck: %w", err) return nil, nil, nil, false, fmt.Errorf("unable to configure healthcheck: %w", err)
} }
paths = []string{"/"} paths = []string{"/"}
if config.Server.Path != "" { if config.Server.Address.Path() != "/" {
paths = append(paths, config.Server.Path) paths = append(paths, config.Server.Address.Path())
} }
return server, listener, paths, isTLS, nil return server, listener, paths, isTLS, nil
@ -93,7 +93,7 @@ func CreateMetricsServer(config *schema.Configuration, providers middlewares.Pro
server = &fasthttp.Server{ server = &fasthttp.Server{
ErrorHandler: handleError(), ErrorHandler: handleError(),
NoDefaultServerHeader: true, NoDefaultServerHeader: true,
Handler: handleMetrics(), Handler: handleMetrics(config.Telemetry.Metrics.Address.Path()),
ReadBufferSize: config.Telemetry.Metrics.Buffers.Read, ReadBufferSize: config.Telemetry.Metrics.Buffers.Read,
WriteBufferSize: config.Telemetry.Metrics.Buffers.Write, WriteBufferSize: config.Telemetry.Metrics.Buffers.Write,
ReadTimeout: config.Telemetry.Metrics.Timeouts.Read, ReadTimeout: config.Telemetry.Metrics.Timeouts.Read,
@ -106,5 +106,5 @@ func CreateMetricsServer(config *schema.Configuration, providers middlewares.Pro
return nil, nil, nil, false, fmt.Errorf("error occurred while attempting to initialize metrics telemetry server listener for address '%s': %w", config.Telemetry.Metrics.Address.String(), err) return nil, nil, nil, false, fmt.Errorf("error occurred while attempting to initialize metrics telemetry server listener for address '%s': %w", config.Telemetry.Metrics.Address.String(), err)
} }
return server, listener, []string{"/metrics"}, false, nil return server, listener, []string{config.Telemetry.Metrics.Address.Path()}, false, nil
} }

View File

@ -256,6 +256,10 @@ func writeHealthCheckEnv(disabled bool, scheme, host, path string, port int) (er
host = "[" + host + "]" host = "[" + host + "]"
} }
if path == "/" {
path = ""
}
_, err = file.WriteString(fmt.Sprintf(healthCheckEnv, scheme, host, port, path)) _, err = file.WriteString(fmt.Sprintf(healthCheckEnv, scheme, host, port, path))
return err return err

View File

@ -6,8 +6,7 @@
jwt_secret: unsecure_secret jwt_secret: unsecure_secret
server: server:
address: 'tcp://:9091' address: 'tcp://:9091/auth'
path: 'auth'
tls: tls:
certificate: /pki/public.backend.crt certificate: /pki/public.backend.crt
key: /pki/private.backend.pem key: /pki/private.backend.pem