2020-04-23 01:47:27 +00:00
|
|
|
package validator
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
2023-01-25 09:36:40 +00:00
|
|
|
"regexp"
|
2021-08-03 09:55:21 +00:00
|
|
|
"strings"
|
2020-04-23 01:47:27 +00:00
|
|
|
|
2021-08-11 01:04:35 +00:00
|
|
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
|
|
|
"github.com/authelia/authelia/v4/internal/utils"
|
2020-04-23 01:47:27 +00:00
|
|
|
)
|
|
|
|
|
2021-08-03 09:55:21 +00:00
|
|
|
// ValidateKeys determines if all provided keys are valid.
|
|
|
|
func ValidateKeys(keys []string, prefix string, validator *schema.StructValidator) {
|
2020-04-23 01:47:27 +00:00
|
|
|
var errStrings []string
|
2020-05-05 19:35:32 +00:00
|
|
|
|
2023-01-25 09:36:40 +00:00
|
|
|
var patterns []*regexp.Regexp
|
|
|
|
|
|
|
|
for _, key := range schema.Keys {
|
|
|
|
pattern, _ := NewKeyPattern(key)
|
|
|
|
|
|
|
|
switch {
|
|
|
|
case pattern == nil:
|
|
|
|
continue
|
|
|
|
default:
|
|
|
|
patterns = append(patterns, pattern)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KEYS:
|
2020-04-23 01:47:27 +00:00
|
|
|
for _, key := range keys {
|
2021-08-03 09:55:21 +00:00
|
|
|
expectedKey := reKeyReplacer.ReplaceAllString(key, "[]")
|
2020-04-23 01:47:27 +00:00
|
|
|
|
2022-04-16 09:00:39 +00:00
|
|
|
if utils.IsStringInSlice(expectedKey, schema.Keys) {
|
2021-03-22 09:04:09 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-08-03 09:55:21 +00:00
|
|
|
if newKey, ok := replacedKeys[expectedKey]; ok {
|
2021-04-16 01:44:37 +00:00
|
|
|
validator.Push(fmt.Errorf(errFmtReplacedConfigurationKey, key, newKey))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-01-25 09:36:40 +00:00
|
|
|
for _, p := range patterns {
|
|
|
|
if p.MatchString(expectedKey) {
|
|
|
|
continue KEYS
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-03 09:55:21 +00:00
|
|
|
if err, ok := specificErrorKeys[expectedKey]; ok {
|
2020-04-23 01:47:27 +00:00
|
|
|
if !utils.IsStringInSlice(err, errStrings) {
|
|
|
|
errStrings = append(errStrings, err)
|
|
|
|
}
|
|
|
|
} else {
|
2021-08-03 09:55:21 +00:00
|
|
|
if strings.HasPrefix(key, prefix) {
|
|
|
|
validator.PushWarning(fmt.Errorf("configuration environment variable not expected: %s", key))
|
|
|
|
} else {
|
|
|
|
validator.Push(fmt.Errorf("configuration key not expected: %s", key))
|
|
|
|
}
|
2020-04-23 01:47:27 +00:00
|
|
|
}
|
|
|
|
}
|
2020-05-05 19:35:32 +00:00
|
|
|
|
2020-04-23 01:47:27 +00:00
|
|
|
for _, err := range errStrings {
|
|
|
|
validator.Push(errors.New(err))
|
|
|
|
}
|
|
|
|
}
|
2023-01-25 09:36:40 +00:00
|
|
|
|
|
|
|
// NewKeyPattern returns patterns which are required to match key patterns.
|
|
|
|
func NewKeyPattern(key string) (pattern *regexp.Regexp, err error) {
|
|
|
|
switch {
|
|
|
|
case strings.Contains(key, ".*."):
|
|
|
|
return NewKeyMapPattern(key)
|
|
|
|
default:
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewKeyMapPattern returns a pattern required to match map keys.
|
|
|
|
func NewKeyMapPattern(key string) (pattern *regexp.Regexp, err error) {
|
|
|
|
parts := strings.Split(key, ".*.")
|
|
|
|
|
|
|
|
buf := &strings.Builder{}
|
|
|
|
|
|
|
|
buf.WriteString("^")
|
|
|
|
|
|
|
|
n := len(parts) - 1
|
|
|
|
|
|
|
|
for i, part := range parts {
|
|
|
|
if i != 0 {
|
|
|
|
buf.WriteString("\\.")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, r := range part {
|
|
|
|
switch r {
|
|
|
|
case '[', ']', '.', '{', '}':
|
|
|
|
buf.WriteRune('\\')
|
|
|
|
fallthrough
|
|
|
|
default:
|
|
|
|
buf.WriteRune(r)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if i < n {
|
|
|
|
buf.WriteString("\\.[a-z0-9]([a-z0-9-_]+)?[a-z0-9]")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.WriteString("$")
|
|
|
|
|
|
|
|
return regexp.Compile(buf.String())
|
|
|
|
}
|