1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2024-11-24 08:52:25 +02:00
oauth2-proxy/pkg/validation/options.go

186 lines
6.2 KiB
Go
Raw Normal View History

2020-04-13 14:50:34 +02:00
package validation
2014-11-09 21:51:10 +02:00
import (
"context"
"crypto/tls"
2014-11-09 21:51:10 +02:00
"fmt"
"net/http"
2014-11-09 21:51:10 +02:00
"net/url"
"strings"
"github.com/mbland/hmacauth"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/options"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/ip"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/logger"
internaloidc "github.com/oauth2-proxy/oauth2-proxy/v7/pkg/providers/oidc"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/util"
2014-11-09 21:51:10 +02:00
)
// Validate checks that required options are set and validates those that they
// are of the correct format
2020-04-13 14:50:34 +02:00
func Validate(o *options.Options) error {
2020-05-25 13:43:24 +02:00
msgs := validateCookie(o.Cookie)
msgs = append(msgs, validateSessionCookieMinimal(o)...)
msgs = append(msgs, validateRedisSessionStore(o)...)
2020-07-23 11:47:31 +02:00
msgs = append(msgs, prefixValues("injectRequestHeaders: ", validateHeaders(o.InjectRequestHeaders)...)...)
msgs = append(msgs, prefixValues("injectResponseHeaders: ", validateHeaders(o.InjectResponseHeaders)...)...)
Multiple providers in alpha config (#947) * Initial commit of multiple provider logic: 1. Created new provider options. 2. Created legacy provider options and conversion options. 3. Added Providers to alpha Options. 4. Started Validation migration of multiple providers 5. Tests. * fixed lint issues * additional lint fixes * Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options * fixed typo * removed weird : file * small CR changes * Removed GoogleGroups validation due to new allowed-groups (including tests). Added line in CHANGELOG * Update pkg/apis/options/providers.go Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Update pkg/apis/options/providers.go Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Update pkg/apis/options/providers.go Co-authored-by: Nick Meves <nick.meves@greenhouse.io> * Initial commit of multiple provider logic: 1. Created new provider options. 2. Created legacy provider options and conversion options. 3. Added Providers to alpha Options. 4. Started Validation migration of multiple providers 5. Tests. * fixed lint issues * additional lint fixes * Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options * small CR changes * auto generates alpha_config.md * rebase (mainly service alpha options related conflicts) * removed : * Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options * small CR changes * Removed GoogleGroups validation due to new allowed-groups (including tests). Added line in CHANGELOG * "cntd. rebase" * ran make generate again * last conflicts * removed duplicate client id validation * 1. Removed provider prefixes 2. altered optionsWithNilProvider logic 3. altered default provider logic 4. moved change in CHANELOG to 7.0.0 * fixed TestGoogleGroupOptions test * ran make generate * moved CHANGLOG line to 7.1.1 * moved changelog comment to 7.1.2 (additional rebase) Co-authored-by: Yana Segal <yana.segal@nielsen.com> Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
2021-04-03 18:06:30 +02:00
msgs = append(msgs, validateProviders(o)...)
msgs = configureLogger(o.Logging, msgs)
msgs = parseSignatureKey(o, msgs)
if o.SSLInsecureSkipVerify {
2020-07-21 03:49:45 +02:00
// InsecureSkipVerify is a configurable option we allow
/* #nosec G402 */
insecureTransport := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
http.DefaultClient = &http.Client{Transport: insecureTransport}
Multiple providers in alpha config (#947) * Initial commit of multiple provider logic: 1. Created new provider options. 2. Created legacy provider options and conversion options. 3. Added Providers to alpha Options. 4. Started Validation migration of multiple providers 5. Tests. * fixed lint issues * additional lint fixes * Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options * fixed typo * removed weird : file * small CR changes * Removed GoogleGroups validation due to new allowed-groups (including tests). Added line in CHANGELOG * Update pkg/apis/options/providers.go Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Update pkg/apis/options/providers.go Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Update pkg/apis/options/providers.go Co-authored-by: Nick Meves <nick.meves@greenhouse.io> * Initial commit of multiple provider logic: 1. Created new provider options. 2. Created legacy provider options and conversion options. 3. Added Providers to alpha Options. 4. Started Validation migration of multiple providers 5. Tests. * fixed lint issues * additional lint fixes * Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options * small CR changes * auto generates alpha_config.md * rebase (mainly service alpha options related conflicts) * removed : * Nits and alterations based on CR: manliy splitting large providers validation function and adding comments to provider options * small CR changes * Removed GoogleGroups validation due to new allowed-groups (including tests). Added line in CHANGELOG * "cntd. rebase" * ran make generate again * last conflicts * removed duplicate client id validation * 1. Removed provider prefixes 2. altered optionsWithNilProvider logic 3. altered default provider logic 4. moved change in CHANELOG to 7.0.0 * fixed TestGoogleGroupOptions test * ran make generate * moved CHANGLOG line to 7.1.1 * moved changelog comment to 7.1.2 (additional rebase) Co-authored-by: Yana Segal <yana.segal@nielsen.com> Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> Co-authored-by: Nick Meves <nick.meves@greenhouse.io>
2021-04-03 18:06:30 +02:00
} else if len(o.Providers[0].CAFiles) > 0 {
pool, err := util.GetCertPool(o.Providers[0].CAFiles)
if err == nil {
transport := http.DefaultTransport.(*http.Transport).Clone()
transport.TLSClientConfig = &tls.Config{
RootCAs: pool,
MinVersion: tls.VersionTLS12,
}
http.DefaultClient = &http.Client{Transport: transport}
} else {
msgs = append(msgs, fmt.Sprintf("unable to load provider CA file(s): %v", err))
}
}
if o.AuthenticatedEmailsFile == "" && len(o.EmailDomains) == 0 && o.HtpasswdFile == "" {
msgs = append(msgs, "missing setting for email validation: email-domain or authenticated-emails-file required."+
"\n use email-domain=* to authorize all email addresses")
}
2014-11-09 21:51:10 +02:00
if o.SkipJwtBearerTokens {
// Configure extra issuers
if len(o.ExtraJwtIssuers) > 0 {
2019-06-06 01:09:29 +02:00
var jwtIssuers []jwtIssuer
2019-05-01 19:00:54 +02:00
jwtIssuers, msgs = parseJwtIssuers(o.ExtraJwtIssuers, msgs)
for _, jwtIssuer := range jwtIssuers {
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 18:12:22 +02:00
verifier, err := newVerifierFromJwtIssuer(
o.Providers[0].OIDCConfig.AudienceClaims,
o.Providers[0].OIDCConfig.ExtraAudiences,
jwtIssuer,
)
if err != nil {
2019-05-01 19:00:54 +02:00
msgs = append(msgs, fmt.Sprintf("error building verifiers: %s", err))
}
2020-04-13 14:50:34 +02:00
o.SetJWTBearerVerifiers(append(o.GetJWTBearerVerifiers(), verifier))
}
}
}
2020-04-13 14:50:34 +02:00
var redirectURL *url.URL
redirectURL, msgs = parseURL(o.RawRedirectURL, "redirect", msgs)
o.SetRedirectURL(redirectURL)
if o.RawRedirectURL == "" && !o.Cookie.Secure && !o.ReverseProxy {
logger.Print("WARNING: no explicit redirect URL: redirects will default to insecure HTTP")
}
2014-11-09 21:51:10 +02:00
msgs = append(msgs, validateUpstreams(o.UpstreamServers)...)
if o.ReverseProxy {
2020-05-23 16:17:41 +02:00
parser, err := ip.GetRealClientIPParser(o.RealClientIPHeader)
if err != nil {
msgs = append(msgs, fmt.Sprintf("real_client_ip_header (%s) not accepted parameter value: %v", o.RealClientIPHeader, err))
}
2020-04-13 14:50:34 +02:00
o.SetRealClientIPParser(parser)
// Allow the logger to get client IPs
logger.SetGetClientFunc(func(r *http.Request) string {
return ip.GetClientString(o.GetRealClientIPParser(), r, false)
})
}
2020-09-23 03:54:32 +02:00
// Do this after ReverseProxy validation for TrustedIP coordinated checks
msgs = append(msgs, validateAllowlists(o)...)
Implements --trusted-ip option (#552) * Implements --ip-whitelist option * Included IPWhitelist option to allow one-or-more selected CIDR ranges to bypass OAuth2 authentication. * Adds IPWhitelist, a fast lookup table for multiple CIDR ranges. * Renamed IPWhitelist ipCIDRSet * Fixed unessesary pointer usage in ipCIDRSet * Update CHANGELOG.md * Update CHANGELOG.md * Updated to not use err.Error() in printf statements * Imrpoved language for --ip-whitelist descriptions. * Improve IP whitelist options error messages * Clarify options single-host normalization * Wrote a book about ipCIDRSet * Added comment to IsWhitelistedIP in oauthproxy.go * Rewrite oauthproxy test case as table driven * oops * Support whitelisting by low-level remote address * Added more test-cases, improved descriptions * Move ip_cidr_set.go to pkg/ip/net_set.go * Add more whitelist test use cases. * Oops * Use subtests for TestIPWhitelist * Add minimal tests for ip.NetSet * Use switch statment * Renamed ip-whitelist to whitelist-ip * Update documentation with a warning. * Update pkg/apis/options/options.go * Update CHANGELOG.md Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Update pkg/ip/net_set_test.go Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Update pkg/ip/net_set_test.go Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Update pkg/ip/net_set_test.go Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * Apply suggestions from code review Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * fix fmt * Move ParseIPNet into abstraction * Add warning in case of --reverse-proxy * Update pkg/validation/options_test.go * Rename --whitelist-ip to --trusted-ip * Update oauthproxy.go Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk> * fix Co-authored-by: Joel Speed <Joel.speed@hotmail.co.uk>
2020-07-11 12:10:58 +02:00
if len(msgs) != 0 {
return fmt.Errorf("invalid configuration:\n %s",
strings.Join(msgs, "\n "))
}
2014-11-09 21:51:10 +02:00
return nil
}
2020-04-13 14:50:34 +02:00
func parseSignatureKey(o *options.Options, msgs []string) []string {
if o.SignatureKey == "" {
return msgs
}
logger.Print("WARNING: `--signature-key` is deprecated. It will be removed in a future release")
components := strings.Split(o.SignatureKey, ":")
if len(components) != 2 {
return append(msgs, "invalid signature hash:key spec: "+
o.SignatureKey)
}
algorithm, secretKey := components[0], components[1]
hash, err := hmacauth.DigestNameToCryptoHash(algorithm)
if err != nil {
return append(msgs, "unsupported signature hash algorithm: "+o.SignatureKey)
}
2020-04-13 14:50:34 +02:00
o.SetSignatureData(&options.SignatureData{Hash: hash, Key: secretKey})
return msgs
}
2016-06-20 13:17:39 +02:00
2019-05-01 19:00:54 +02:00
// parseJwtIssuers takes in an array of strings in the form of issuer=audience
2019-06-06 01:09:29 +02:00
// and parses to an array of jwtIssuer structs.
func parseJwtIssuers(issuers []string, msgs []string) ([]jwtIssuer, []string) {
parsedIssuers := make([]jwtIssuer, 0, len(issuers))
2019-05-01 19:00:54 +02:00
for _, jwtVerifier := range issuers {
components := strings.Split(jwtVerifier, "=")
if len(components) < 2 {
2019-05-01 19:00:54 +02:00
msgs = append(msgs, fmt.Sprintf("invalid jwt verifier uri=audience spec: %s", jwtVerifier))
continue
}
uri, audience := components[0], strings.Join(components[1:], "=")
2019-06-06 01:09:29 +02:00
parsedIssuers = append(parsedIssuers, jwtIssuer{issuerURI: uri, audience: audience})
}
2019-05-01 19:00:54 +02:00
return parsedIssuers, msgs
}
2019-06-06 01:09:29 +02:00
// newVerifierFromJwtIssuer takes in issuer information in jwtIssuer info and returns
2019-05-01 19:00:54 +02:00
// a verifier for that issuer.
func newVerifierFromJwtIssuer(audienceClaims []string, extraAudiences []string, jwtIssuer jwtIssuer) (internaloidc.IDTokenVerifier, error) {
pvOpts := internaloidc.ProviderVerifierOptions{
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 18:12:22 +02:00
AudienceClaims: audienceClaims,
ClientID: jwtIssuer.audience,
ExtraAudiences: extraAudiences,
IssuerURL: jwtIssuer.issuerURI,
}
pv, err := internaloidc.NewProviderVerifier(context.TODO(), pvOpts)
if err != nil {
// If the discovery didn't work, try again without discovery
pvOpts.JWKsURL = strings.TrimSuffix(jwtIssuer.issuerURI, "/") + "/.well-known/jwks.json"
pvOpts.SkipDiscovery = true
pv, err = internaloidc.NewProviderVerifier(context.TODO(), pvOpts)
if err != nil {
return nil, fmt.Errorf("could not construct provider verifier for JWT Issuer: %v", err)
}
improved audience handling to support client credentials access tokens without aud claims (#1204) * implementation draft * add cfg options skip-au-when-missing && client-id-verification-claim; enhance the provider data verification logic for sake of the added options * refactor configs, added logging and add additional claim verification * simplify logic by just having one configuration similar to oidc-email-claim * added internal oidc token verifier, so that aud check behavior can be managed with oauth2-proxy and is compatible with extra-jwt-issuers * refactored verification to reduce complexity * refactored verification to reduce complexity * added docs * adjust tests to support new OIDCAudienceClaim and OIDCExtraAudiences options * extend unit tests and ensure that audience is set with the value of aud claim configuration * revert filemodes and update docs * update docs * remove unneccesary logging, refactor audience existence check and added additional unit tests * fix linting issues after rebase on origin/main * cleanup: use new imports for migrated libraries after rebase on origin/main * adapt mock in keycloak_oidc_test.go * allow specifying multiple audience claims, fixed bug where jwt issuers client id was not the being considered and fixed bug where aud claims with multiple audiences has broken the whole validation * fixed formatting issue * do not pass the whole options struct to minimize complexity and dependency to the configuration structure * added changelog entry * update docs Co-authored-by: Sofia Weiler <sofia.weiler@aoe.com> Co-authored-by: Christian Zenker <christian.zenker@aoe.com>
2022-02-15 18:12:22 +02:00
}
return pv.Verifier(), nil
}
2020-04-13 14:50:34 +02:00
// jwtIssuer hold parsed JWT issuer info that's used to construct a verifier.
type jwtIssuer struct {
issuerURI string
audience string
}
func parseURL(toParse string, urltype string, msgs []string) (*url.URL, []string) {
parsed, err := url.Parse(toParse)
if err != nil {
return nil, append(msgs, fmt.Sprintf(
"error parsing %s-url=%q %s", urltype, toParse, err))
}
return parsed, msgs
}