From d26c65ba8d3f487eb4535e246e750ae664977c56 Mon Sep 17 00:00:00 2001 From: Joel Speed Date: Thu, 23 Jul 2020 10:47:31 +0100 Subject: [PATCH] Add validation for Headers struct --- pkg/validation/common.go | 44 +++++++++++++++++++++++++++ pkg/validation/header.go | 63 +++++++++++++++++++++++++++++++++++++++ pkg/validation/options.go | 2 ++ pkg/validation/utils.go | 11 +++++++ 4 files changed, 120 insertions(+) create mode 100644 pkg/validation/common.go create mode 100644 pkg/validation/header.go create mode 100644 pkg/validation/utils.go diff --git a/pkg/validation/common.go b/pkg/validation/common.go new file mode 100644 index 00000000..ccde822d --- /dev/null +++ b/pkg/validation/common.go @@ -0,0 +1,44 @@ +package validation + +import ( + "encoding/base64" + "fmt" + "os" + + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" +) + +func validateSecretSource(source options.SecretSource) string { + switch { + case len(source.Value) > 0 && source.FromEnv == "" && source.FromFile == "": + return validateSecretSourceValue(source.Value) + case len(source.Value) == 0 && source.FromEnv != "" && source.FromFile == "": + return validateSecretSourceEnv(source.FromEnv) + case len(source.Value) == 0 && source.FromEnv == "" && source.FromFile != "": + return validateSecretSourceFile(source.FromFile) + default: + return "multiple values specified for secret source: specify either value, fromEnv of fromFile" + } +} + +func validateSecretSourceValue(value []byte) string { + dst := make([]byte, len(value)) + if _, err := base64.StdEncoding.Decode(dst, value); err != nil { + return fmt.Sprintf("error decoding secret value: %v", err) + } + return "" +} + +func validateSecretSourceEnv(key string) string { + if value := os.Getenv(key); value == "" { + return fmt.Sprintf("error loading secret from environent: no value for for key %q", key) + } + return "" +} + +func validateSecretSourceFile(path string) string { + if _, err := os.Stat(path); err != nil { + return fmt.Sprintf("error loadig secret from file: %v", err) + } + return "" +} diff --git a/pkg/validation/header.go b/pkg/validation/header.go new file mode 100644 index 00000000..603feaf4 --- /dev/null +++ b/pkg/validation/header.go @@ -0,0 +1,63 @@ +package validation + +import ( + "fmt" + + "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options" +) + +func validateHeaders(headers []options.Header) []string { + msgs := []string{} + names := make(map[string]struct{}) + + for _, header := range headers { + msgs = append(msgs, validateHeader(header, names)...) + } + return msgs +} + +func validateHeader(header options.Header, names map[string]struct{}) []string { + msgs := []string{} + + if header.Name == "" { + msgs = append(msgs, "header has empty name: names are required for all headers") + } + + if _, ok := names[header.Name]; ok { + msgs = append(msgs, fmt.Sprintf("multiple headers found with name %q: header names must be unique", header.Name)) + } + names[header.Name] = struct{}{} + + for _, value := range header.Values { + msgs = append(msgs, + prefixValues(fmt.Sprintf("invalid header %q: invalid values: ", header.Name), + validateHeaderValue(header.Name, value)..., + )..., + ) + } + return msgs +} + +func validateHeaderValue(name string, value options.HeaderValue) []string { + switch { + case value.SecretSource != nil && value.ClaimSource == nil: + return []string{validateSecretSource(*value.SecretSource)} + case value.SecretSource == nil && value.ClaimSource != nil: + return validateHeaderValueClaimSource(*value.ClaimSource) + default: + return []string{"header value has multiple entries: only one entry per value is allowed"} + } +} + +func validateHeaderValueClaimSource(claim options.ClaimSource) []string { + msgs := []string{} + + if claim.Claim == "" { + msgs = append(msgs, "claim should not be empty") + } + + if claim.BasicAuthPassword != nil { + msgs = append(msgs, prefixValues("invalid basicAuthPassword: ", validateSecretSource(*claim.BasicAuthPassword))...) + } + return msgs +} diff --git a/pkg/validation/options.go b/pkg/validation/options.go index b54df330..29d8f71e 100644 --- a/pkg/validation/options.go +++ b/pkg/validation/options.go @@ -28,6 +28,8 @@ func Validate(o *options.Options) error { msgs := validateCookie(o.Cookie) msgs = append(msgs, validateSessionCookieMinimal(o)...) msgs = append(msgs, validateRedisSessionStore(o)...) + msgs = append(msgs, prefixValues("injectRequestHeaders: ", validateHeaders(o.InjectRequestHeaders)...)...) + msgs = append(msgs, prefixValues("injectRespeonseHeaders: ", validateHeaders(o.InjectRequestHeaders)...)...) if o.SSLInsecureSkipVerify { // InsecureSkipVerify is a configurable option we allow diff --git a/pkg/validation/utils.go b/pkg/validation/utils.go new file mode 100644 index 00000000..0ef3e15f --- /dev/null +++ b/pkg/validation/utils.go @@ -0,0 +1,11 @@ +package validation + +func prefixValues(prefix string, values ...string) []string { + msgs := []string{} + for _, value := range values { + if value != "" { + msgs = append(msgs, prefix+value) + } + } + return msgs +}