mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-02-27 08:13:52 +00:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39a95e1198 | ||
|
|
6d3ed73eee | ||
|
|
e3a963b73f | ||
|
|
30818cb66d | ||
|
|
976035115e | ||
|
|
85b67f254c | ||
|
|
e1a0367b03 | ||
|
|
a9aac69c65 | ||
|
|
d88895c4a5 | ||
|
|
d35306aa85 | ||
|
|
3548362ce4 | ||
|
|
4951cbe5d4 | ||
|
|
66f4ee8a1b | ||
|
|
09b9075abb | ||
|
|
99c635c38d | ||
|
|
265c63fa54 | ||
|
|
2995e6a48c |
@@ -3,7 +3,7 @@
|
||||
# Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
FROM golang:1.19.1 as build-env
|
||||
FROM golang:1.19.4 as build-env
|
||||
|
||||
WORKDIR /work
|
||||
COPY . .
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
# Pinniped Maintainers
|
||||
# Current Pinniped Maintainers
|
||||
|
||||
This is the current list of maintainers for the Pinniped project.
|
||||
|
||||
| Maintainer | GitHub ID | Affiliation |
|
||||
| --------------- | --------- | ----------- |
|
||||
| Anjali Telang | [anjaltelang](https://github.com/anjaltelang) | [VMware](https://www.github.com/vmware/) |
|
||||
| Ryan Richard | [cfryanr](https://github.com/cfryanr) | [VMware](https://www.github.com/vmware/) |
|
||||
| Ben Petersen | [benjaminapetersen](https://github.com/benjaminapetersen) | [VMware](https://www.github.com/vmware/) |
|
||||
| Maintainer | GitHub ID | Affiliation |
|
||||
|-----------------|-----------------------------------------------------------|------------------------------------------|
|
||||
| Ben Petersen | [benjaminapetersen](https://github.com/benjaminapetersen) | [VMware](https://www.github.com/vmware/) |
|
||||
| Ryan Richard | [cfryanr](https://github.com/cfryanr) | [VMware](https://www.github.com/vmware/) |
|
||||
| Joshua T. Casey | [joshuatcasey](https://github.com/joshuatcasey) | [VMware](https://www.github.com/vmware/) |
|
||||
|
||||
## Emeritus Maintainers
|
||||
|
||||
* Andrew Keesler, [ankeesler](https://github.com/ankeesler)
|
||||
* Pablo Schuhmacher, [pabloschuhmacher](https://github.com/pabloschuhmacher)
|
||||
* Matt Moyer, [mattmoyer](https://github.com/mattmoyer)
|
||||
* Margo Crawford, [margocrawf](https://github.com/margocrawf)
|
||||
* Mo Khan, [enj](https://github.com/enj)
|
||||
| Maintainer | GitHub ID |
|
||||
|-------------------|---------------------------------------------------------|
|
||||
| Andrew Keesler | [ankeesler](https://github.com/ankeesler) |
|
||||
| Anjali Telang | [anjaltelang](https://github.com/anjaltelang) |
|
||||
| Margo Crawford | [margocrawf](https://github.com/margocrawf) |
|
||||
| Matt Moyer | [mattmoyer](https://github.com/mattmoyer) |
|
||||
| Mo Khan | [enj](https://github.com/enj) |
|
||||
| Pablo Schuhmacher | [pabloschuhmacher](https://github.com/pabloschuhmacher) |
|
||||
|
||||
## Pinniped Contributors & Stakeholders
|
||||
## Pinniped Community Management
|
||||
|
||||
| Feature Area | Lead |
|
||||
| ----------------------------- | :---------------------: |
|
||||
| Technical Lead | Ryan Richard (cfryanr) |
|
||||
| Product Management | Anjali Telang (anjaltelang) |
|
||||
| Community Management | Nigel Brown (pnbrown) |
|
||||
| Community Manager | GitHub ID |
|
||||
|-------------------|---------------------------------------|
|
||||
| Nigel Brown | [pnbrown](https://github.com/pnbrown) |
|
||||
55
go.mod
55
go.mod
@@ -2,21 +2,6 @@ module go.pinniped.dev
|
||||
|
||||
go 1.17
|
||||
|
||||
// Unfortuntely, having any indirect dependency on github.com/oleiade/reflections@v1.0.0
|
||||
// seems to cause Dependabot to stop scanning our dependencies due to a checksum error for the package.
|
||||
// The cause of the checksum error is described in https://github.com/oleiade/reflections/issues/14.
|
||||
//
|
||||
// According to `go mod graph`, this dependency is (currently) coming from:
|
||||
// go.pinniped.dev -> github.com/ory/x@v0.0.212 -> github.com/ory/analytics-go/v4@v4.0.0 -> github.com/ory/x@v0.0.110 -> github.com/ory/fosite@v0.29.0 -> github.com/oleiade/reflections@v1.0.0
|
||||
// So the issue is that older versions of ory/x had a direct dependency on an old version of Fosite.
|
||||
// Newer versions of ory/x do not depend on fosite anymore. We can use a replace directive until none
|
||||
// of our indirect dependencies pull in any old versions of ory/x anymore.
|
||||
//
|
||||
// Whenever we upgrade fosite and ory/x, we can try removing this replace directive and running
|
||||
// `go mod download` to see if github.com/oleiade/reflections@v1.0.0 still appears in our go.sum.
|
||||
// As long as it does, we probably need to keep this replace directive.
|
||||
replace github.com/oleiade/reflections => github.com/oleiade/reflections v1.0.1
|
||||
|
||||
// bumping github.com/ory/x to higher than v0.0.297 breaks k8s.io/apiserver via go.opentelemetry.io/otel/semconv
|
||||
// force the use of an old version for now as it seems to allow a newer ory/x without breaking the apiserver lib.
|
||||
// all go.opentelemetry.io replace directives are copied from:
|
||||
@@ -55,23 +40,23 @@ require (
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||
github.com/ory/fosite v0.42.2
|
||||
github.com/ory/fosite v0.44.0
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sclevine/agouti v3.0.0+incompatible
|
||||
github.com/sclevine/spec v1.4.0
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/tdewolff/minify/v2 v2.12.2
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/tdewolff/minify/v2 v2.12.4
|
||||
go.uber.org/atomic v1.10.0
|
||||
go.uber.org/zap v1.23.0
|
||||
golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0
|
||||
golang.org/x/net v0.0.0-20220923203811-8be639271d50
|
||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
|
||||
golang.org/x/sync v0.0.0-20220923202941-7f9b1623fab7
|
||||
golang.org/x/term v0.0.0-20220919170432-7a66f970e087
|
||||
golang.org/x/text v0.3.7
|
||||
go.uber.org/zap v1.24.0
|
||||
golang.org/x/crypto v0.4.0
|
||||
golang.org/x/net v0.4.0
|
||||
golang.org/x/oauth2 v0.3.0
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/term v0.3.0
|
||||
golang.org/x/text v0.5.0
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
k8s.io/api v0.25.2
|
||||
k8s.io/apiextensions-apiserver v0.25.2
|
||||
@@ -79,11 +64,11 @@ require (
|
||||
k8s.io/apiserver v0.25.2
|
||||
k8s.io/client-go v0.25.2
|
||||
k8s.io/component-base v0.25.2
|
||||
k8s.io/gengo v0.0.0-20220913193501-391367153a38
|
||||
k8s.io/gengo v0.0.0-20221011193443-fad74ee6edd9
|
||||
k8s.io/klog/v2 v2.80.1
|
||||
k8s.io/kube-aggregator v0.25.2
|
||||
k8s.io/kube-openapi v0.0.0-20220803164354-a70c9af30aea
|
||||
k8s.io/utils v0.0.0-20220922133306-665eaaec4324
|
||||
k8s.io/kube-openapi v0.0.0-20221207184640-f3cff1453715
|
||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
@@ -105,8 +90,11 @@ require (
|
||||
github.com/coreos/go-semver v0.3.0 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/cristalhq/jwt/v4 v4.0.2 // indirect
|
||||
github.com/dave/jennifer v1.4.0 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/ecordell/optgen v0.0.6 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||
github.com/form3tech-oss/jwt-go v3.2.5+incompatible // indirect
|
||||
@@ -123,9 +111,11 @@ require (
|
||||
github.com/google/gnostic v0.6.9 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.13 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
@@ -138,6 +128,7 @@ require (
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/ory/go-acc v0.2.8 // indirect
|
||||
github.com/ory/go-convenience v0.1.0 // indirect
|
||||
github.com/ory/viper v1.7.5 // indirect
|
||||
@@ -155,7 +146,7 @@ require (
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.0 // indirect
|
||||
github.com/tdewolff/parse/v2 v2.6.3 // indirect
|
||||
github.com/tdewolff/parse/v2 v2.6.4 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.4 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.4 // indirect
|
||||
@@ -172,7 +163,7 @@ require (
|
||||
go.opentelemetry.io/proto/otlp v0.15.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
# any type of fips certification.
|
||||
|
||||
# use go-boringcrypto rather than main go
|
||||
FROM us-docker.pkg.dev/google.com/api-project-999119582588/go-boringcrypto/golang:1.18.6b7 as build-env
|
||||
FROM us-docker.pkg.dev/google.com/api-project-999119582588/go-boringcrypto/golang:1.18.9b7 as build-env
|
||||
|
||||
WORKDIR /work
|
||||
COPY . .
|
||||
|
||||
@@ -93,39 +93,39 @@ func FromPath(ctx context.Context, path string) (*Config, error) {
|
||||
|
||||
func maybeSetAPIDefaults(apiConfig *APIConfigSpec) {
|
||||
if apiConfig.ServingCertificateConfig.DurationSeconds == nil {
|
||||
apiConfig.ServingCertificateConfig.DurationSeconds = pointer.Int64Ptr(aboutAYear)
|
||||
apiConfig.ServingCertificateConfig.DurationSeconds = pointer.Int64(aboutAYear)
|
||||
}
|
||||
|
||||
if apiConfig.ServingCertificateConfig.RenewBeforeSeconds == nil {
|
||||
apiConfig.ServingCertificateConfig.RenewBeforeSeconds = pointer.Int64Ptr(about9Months)
|
||||
apiConfig.ServingCertificateConfig.RenewBeforeSeconds = pointer.Int64(about9Months)
|
||||
}
|
||||
}
|
||||
|
||||
func maybeSetAPIGroupSuffixDefault(apiGroupSuffix **string) {
|
||||
if *apiGroupSuffix == nil {
|
||||
*apiGroupSuffix = pointer.StringPtr(groupsuffix.PinnipedDefaultSuffix)
|
||||
*apiGroupSuffix = pointer.String(groupsuffix.PinnipedDefaultSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
func maybeSetAggregatedAPIServerPortDefaults(port **int64) {
|
||||
if *port == nil {
|
||||
*port = pointer.Int64Ptr(aggregatedAPIServerPortDefault)
|
||||
*port = pointer.Int64(aggregatedAPIServerPortDefault)
|
||||
}
|
||||
}
|
||||
|
||||
func maybeSetImpersonationProxyServerPortDefaults(port **int64) {
|
||||
if *port == nil {
|
||||
*port = pointer.Int64Ptr(impersonationProxyPortDefault)
|
||||
*port = pointer.Int64(impersonationProxyPortDefault)
|
||||
}
|
||||
}
|
||||
|
||||
func maybeSetKubeCertAgentDefaults(cfg *KubeCertAgentSpec) {
|
||||
if cfg.NamePrefix == nil {
|
||||
cfg.NamePrefix = pointer.StringPtr("pinniped-kube-cert-agent-")
|
||||
cfg.NamePrefix = pointer.String("pinniped-kube-cert-agent-")
|
||||
}
|
||||
|
||||
if cfg.Image == nil {
|
||||
cfg.Image = pointer.StringPtr("debian:latest")
|
||||
cfg.Image = pointer.String("debian:latest")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,17 +59,17 @@ func TestFromPath(t *testing.T) {
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
DiscoveryInfo: DiscoveryInfoSpec{
|
||||
URL: pointer.StringPtr("https://some.discovery/url"),
|
||||
URL: pointer.String("https://some.discovery/url"),
|
||||
},
|
||||
APIConfig: APIConfigSpec{
|
||||
ServingCertificateConfig: ServingCertificateConfigSpec{
|
||||
DurationSeconds: pointer.Int64Ptr(3600),
|
||||
RenewBeforeSeconds: pointer.Int64Ptr(2400),
|
||||
DurationSeconds: pointer.Int64(3600),
|
||||
RenewBeforeSeconds: pointer.Int64(2400),
|
||||
},
|
||||
},
|
||||
APIGroupSuffix: pointer.StringPtr("some.suffix.com"),
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(12345),
|
||||
ImpersonationProxyServerPort: pointer.Int64Ptr(4242),
|
||||
APIGroupSuffix: pointer.String("some.suffix.com"),
|
||||
AggregatedAPIServerPort: pointer.Int64(12345),
|
||||
ImpersonationProxyServerPort: pointer.Int64(4242),
|
||||
NamesConfig: NamesConfigSpec{
|
||||
ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate",
|
||||
CredentialIssuer: "pinniped-config",
|
||||
@@ -86,8 +86,8 @@ func TestFromPath(t *testing.T) {
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
KubeCertAgentConfig: KubeCertAgentSpec{
|
||||
NamePrefix: pointer.StringPtr("kube-cert-agent-name-prefix-"),
|
||||
Image: pointer.StringPtr("kube-cert-agent-image"),
|
||||
NamePrefix: pointer.String("kube-cert-agent-name-prefix-"),
|
||||
Image: pointer.String("kube-cert-agent-image"),
|
||||
ImagePullSecrets: []string{"kube-cert-agent-image-pull-secret"},
|
||||
},
|
||||
LogLevel: func(level plog.LogLevel) *plog.LogLevel { return &level }(plog.LevelDebug),
|
||||
@@ -135,17 +135,17 @@ func TestFromPath(t *testing.T) {
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
DiscoveryInfo: DiscoveryInfoSpec{
|
||||
URL: pointer.StringPtr("https://some.discovery/url"),
|
||||
URL: pointer.String("https://some.discovery/url"),
|
||||
},
|
||||
APIConfig: APIConfigSpec{
|
||||
ServingCertificateConfig: ServingCertificateConfigSpec{
|
||||
DurationSeconds: pointer.Int64Ptr(3600),
|
||||
RenewBeforeSeconds: pointer.Int64Ptr(2400),
|
||||
DurationSeconds: pointer.Int64(3600),
|
||||
RenewBeforeSeconds: pointer.Int64(2400),
|
||||
},
|
||||
},
|
||||
APIGroupSuffix: pointer.StringPtr("some.suffix.com"),
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(12345),
|
||||
ImpersonationProxyServerPort: pointer.Int64Ptr(4242),
|
||||
APIGroupSuffix: pointer.String("some.suffix.com"),
|
||||
AggregatedAPIServerPort: pointer.Int64(12345),
|
||||
ImpersonationProxyServerPort: pointer.Int64(4242),
|
||||
NamesConfig: NamesConfigSpec{
|
||||
ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate",
|
||||
CredentialIssuer: "pinniped-config",
|
||||
@@ -162,8 +162,8 @@ func TestFromPath(t *testing.T) {
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
KubeCertAgentConfig: KubeCertAgentSpec{
|
||||
NamePrefix: pointer.StringPtr("kube-cert-agent-name-prefix-"),
|
||||
Image: pointer.StringPtr("kube-cert-agent-image"),
|
||||
NamePrefix: pointer.String("kube-cert-agent-name-prefix-"),
|
||||
Image: pointer.String("kube-cert-agent-image"),
|
||||
ImagePullSecrets: []string{"kube-cert-agent-image-pull-secret"},
|
||||
},
|
||||
Log: plog.LogSpec{
|
||||
@@ -212,17 +212,17 @@ func TestFromPath(t *testing.T) {
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
DiscoveryInfo: DiscoveryInfoSpec{
|
||||
URL: pointer.StringPtr("https://some.discovery/url"),
|
||||
URL: pointer.String("https://some.discovery/url"),
|
||||
},
|
||||
APIConfig: APIConfigSpec{
|
||||
ServingCertificateConfig: ServingCertificateConfigSpec{
|
||||
DurationSeconds: pointer.Int64Ptr(3600),
|
||||
RenewBeforeSeconds: pointer.Int64Ptr(2400),
|
||||
DurationSeconds: pointer.Int64(3600),
|
||||
RenewBeforeSeconds: pointer.Int64(2400),
|
||||
},
|
||||
},
|
||||
APIGroupSuffix: pointer.StringPtr("some.suffix.com"),
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(12345),
|
||||
ImpersonationProxyServerPort: pointer.Int64Ptr(4242),
|
||||
APIGroupSuffix: pointer.String("some.suffix.com"),
|
||||
AggregatedAPIServerPort: pointer.Int64(12345),
|
||||
ImpersonationProxyServerPort: pointer.Int64(4242),
|
||||
NamesConfig: NamesConfigSpec{
|
||||
ServingCertificateSecret: "pinniped-concierge-api-tls-serving-certificate",
|
||||
CredentialIssuer: "pinniped-config",
|
||||
@@ -239,8 +239,8 @@ func TestFromPath(t *testing.T) {
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
},
|
||||
KubeCertAgentConfig: KubeCertAgentSpec{
|
||||
NamePrefix: pointer.StringPtr("kube-cert-agent-name-prefix-"),
|
||||
Image: pointer.StringPtr("kube-cert-agent-image"),
|
||||
NamePrefix: pointer.String("kube-cert-agent-name-prefix-"),
|
||||
Image: pointer.String("kube-cert-agent-image"),
|
||||
ImagePullSecrets: []string{"kube-cert-agent-image-pull-secret"},
|
||||
},
|
||||
LogLevel: func(level plog.LogLevel) *plog.LogLevel { return &level }(plog.LevelDebug),
|
||||
@@ -289,13 +289,13 @@ func TestFromPath(t *testing.T) {
|
||||
DiscoveryInfo: DiscoveryInfoSpec{
|
||||
URL: nil,
|
||||
},
|
||||
APIGroupSuffix: pointer.StringPtr("pinniped.dev"),
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(10250),
|
||||
ImpersonationProxyServerPort: pointer.Int64Ptr(8444),
|
||||
APIGroupSuffix: pointer.String("pinniped.dev"),
|
||||
AggregatedAPIServerPort: pointer.Int64(10250),
|
||||
ImpersonationProxyServerPort: pointer.Int64(8444),
|
||||
APIConfig: APIConfigSpec{
|
||||
ServingCertificateConfig: ServingCertificateConfigSpec{
|
||||
DurationSeconds: pointer.Int64Ptr(60 * 60 * 24 * 365), // about a year
|
||||
RenewBeforeSeconds: pointer.Int64Ptr(60 * 60 * 24 * 30 * 9), // about 9 months
|
||||
DurationSeconds: pointer.Int64(60 * 60 * 24 * 365), // about a year
|
||||
RenewBeforeSeconds: pointer.Int64(60 * 60 * 24 * 30 * 9), // about 9 months
|
||||
},
|
||||
},
|
||||
NamesConfig: NamesConfigSpec{
|
||||
@@ -311,8 +311,8 @@ func TestFromPath(t *testing.T) {
|
||||
},
|
||||
Labels: map[string]string{},
|
||||
KubeCertAgentConfig: KubeCertAgentSpec{
|
||||
NamePrefix: pointer.StringPtr("pinniped-kube-cert-agent-"),
|
||||
Image: pointer.StringPtr("debian:latest"),
|
||||
NamePrefix: pointer.String("pinniped-kube-cert-agent-"),
|
||||
Image: pointer.String("debian:latest"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -109,7 +109,7 @@ func maybeSetEndpointDefault(endpoint **Endpoint, defaultEndpoint Endpoint) {
|
||||
|
||||
func maybeSetAPIGroupSuffixDefault(apiGroupSuffix **string) {
|
||||
if *apiGroupSuffix == nil {
|
||||
*apiGroupSuffix = pointer.StringPtr(groupsuffix.PinnipedDefaultSuffix)
|
||||
*apiGroupSuffix = pointer.String(groupsuffix.PinnipedDefaultSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ func validateAPIGroupSuffix(apiGroupSuffix string) error {
|
||||
|
||||
func maybeSetAggregatedAPIServerPortDefaults(port **int64) {
|
||||
if *port == nil {
|
||||
*port = pointer.Int64Ptr(aggregatedAPIServerPortDefault)
|
||||
*port = pointer.Int64(aggregatedAPIServerPortDefault)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestFromPath(t *testing.T) {
|
||||
aggregatedAPIServerPort: 12345
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
APIGroupSuffix: pointer.StringPtr("some.suffix.com"),
|
||||
APIGroupSuffix: pointer.String("some.suffix.com"),
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
@@ -68,7 +68,7 @@ func TestFromPath(t *testing.T) {
|
||||
Log: plog.LogSpec{
|
||||
Level: plog.LevelTrace,
|
||||
},
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(12345),
|
||||
AggregatedAPIServerPort: pointer.Int64(12345),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -95,7 +95,7 @@ func TestFromPath(t *testing.T) {
|
||||
aggregatedAPIServerPort: 12345
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
APIGroupSuffix: pointer.StringPtr("some.suffix.com"),
|
||||
APIGroupSuffix: pointer.String("some.suffix.com"),
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
@@ -118,7 +118,7 @@ func TestFromPath(t *testing.T) {
|
||||
Level: plog.LevelInfo,
|
||||
Format: plog.FormatText,
|
||||
},
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(12345),
|
||||
AggregatedAPIServerPort: pointer.Int64(12345),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -145,7 +145,7 @@ func TestFromPath(t *testing.T) {
|
||||
format: text
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
APIGroupSuffix: pointer.StringPtr("some.suffix.com"),
|
||||
APIGroupSuffix: pointer.String("some.suffix.com"),
|
||||
Labels: map[string]string{
|
||||
"myLabelKey1": "myLabelValue1",
|
||||
"myLabelKey2": "myLabelValue2",
|
||||
@@ -169,7 +169,7 @@ func TestFromPath(t *testing.T) {
|
||||
Level: plog.LevelTrace,
|
||||
Format: plog.FormatText,
|
||||
},
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(10250),
|
||||
AggregatedAPIServerPort: pointer.Int64(10250),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -192,7 +192,7 @@ func TestFromPath(t *testing.T) {
|
||||
defaultTLSCertificateSecret: my-secret-name
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
APIGroupSuffix: pointer.StringPtr("pinniped.dev"),
|
||||
APIGroupSuffix: pointer.String("pinniped.dev"),
|
||||
Labels: map[string]string{},
|
||||
NamesConfig: NamesConfigSpec{
|
||||
DefaultTLSCertificateSecret: "my-secret-name",
|
||||
@@ -207,7 +207,7 @@ func TestFromPath(t *testing.T) {
|
||||
},
|
||||
},
|
||||
AllowExternalHTTP: false,
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(10250),
|
||||
AggregatedAPIServerPort: pointer.Int64(10250),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -322,7 +322,7 @@ func TestFromPath(t *testing.T) {
|
||||
insecureAcceptExternalUnencryptedHttpRequests: true
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
APIGroupSuffix: pointer.StringPtr("pinniped.dev"),
|
||||
APIGroupSuffix: pointer.String("pinniped.dev"),
|
||||
Labels: map[string]string{},
|
||||
NamesConfig: NamesConfigSpec{
|
||||
DefaultTLSCertificateSecret: "my-secret-name",
|
||||
@@ -338,7 +338,7 @@ func TestFromPath(t *testing.T) {
|
||||
},
|
||||
},
|
||||
AllowExternalHTTP: true,
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(10250),
|
||||
AggregatedAPIServerPort: pointer.Int64(10250),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -354,7 +354,7 @@ func TestFromPath(t *testing.T) {
|
||||
insecureAcceptExternalUnencryptedHttpRequests: "true"
|
||||
`),
|
||||
wantConfig: &Config{
|
||||
APIGroupSuffix: pointer.StringPtr("pinniped.dev"),
|
||||
APIGroupSuffix: pointer.String("pinniped.dev"),
|
||||
Labels: map[string]string{},
|
||||
NamesConfig: NamesConfigSpec{
|
||||
DefaultTLSCertificateSecret: "my-secret-name",
|
||||
@@ -370,7 +370,7 @@ func TestFromPath(t *testing.T) {
|
||||
},
|
||||
},
|
||||
AllowExternalHTTP: true,
|
||||
AggregatedAPIServerPort: pointer.Int64Ptr(10250),
|
||||
AggregatedAPIServerPort: pointer.Int64(10250),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -521,14 +521,14 @@ func (c *agentController) newAgentDeployment(controllerManagerPod *corev1.Pod) *
|
||||
Labels: c.cfg.Labels,
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Replicas: pointer.Int32Ptr(1),
|
||||
Replicas: pointer.Int32(1),
|
||||
Selector: metav1.SetAsLabelSelector(c.cfg.agentPodSelectorLabels()),
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: c.cfg.agentPodLabels(),
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
TerminationGracePeriodSeconds: pointer.Int64Ptr(0),
|
||||
TerminationGracePeriodSeconds: pointer.Int64(0),
|
||||
ImagePullSecrets: imagePullSecrets,
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
@@ -556,15 +556,15 @@ func (c *agentController) newAgentDeployment(controllerManagerPod *corev1.Pod) *
|
||||
Volumes: controllerManagerPod.Spec.Volumes,
|
||||
RestartPolicy: corev1.RestartPolicyAlways,
|
||||
NodeSelector: controllerManagerPod.Spec.NodeSelector,
|
||||
AutomountServiceAccountToken: pointer.BoolPtr(false),
|
||||
AutomountServiceAccountToken: pointer.Bool(false),
|
||||
ServiceAccountName: c.cfg.ServiceAccountName,
|
||||
NodeName: controllerManagerPod.Spec.NodeName,
|
||||
Tolerations: controllerManagerPod.Spec.Tolerations,
|
||||
// We need to run the agent pod as root since the file permissions
|
||||
// on the cluster keypair usually restricts access to only root.
|
||||
SecurityContext: &corev1.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(0),
|
||||
RunAsGroup: pointer.Int64Ptr(0),
|
||||
RunAsUser: pointer.Int64(0),
|
||||
RunAsGroup: pointer.Int64(0),
|
||||
},
|
||||
HostNetwork: controllerManagerPod.Spec.HostNetwork,
|
||||
},
|
||||
|
||||
@@ -95,7 +95,7 @@ func TestAgentController(t *testing.T) {
|
||||
Labels: map[string]string{"extralabel": "labelvalue", "app": "anything"},
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Replicas: pointer.Int32Ptr(1),
|
||||
Replicas: pointer.Int32(1),
|
||||
Selector: metav1.SetAsLabelSelector(map[string]string{
|
||||
"kube-cert-agent.pinniped.dev": "v3",
|
||||
}),
|
||||
@@ -133,12 +133,12 @@ func TestAgentController(t *testing.T) {
|
||||
ImagePullPolicy: corev1.PullIfNotPresent,
|
||||
}},
|
||||
RestartPolicy: corev1.RestartPolicyAlways,
|
||||
TerminationGracePeriodSeconds: pointer.Int64Ptr(0),
|
||||
TerminationGracePeriodSeconds: pointer.Int64(0),
|
||||
ServiceAccountName: "test-service-account-name",
|
||||
AutomountServiceAccountToken: pointer.BoolPtr(false),
|
||||
AutomountServiceAccountToken: pointer.Bool(false),
|
||||
SecurityContext: &corev1.PodSecurityContext{
|
||||
RunAsUser: pointer.Int64Ptr(0),
|
||||
RunAsGroup: pointer.Int64Ptr(0),
|
||||
RunAsUser: pointer.Int64(0),
|
||||
RunAsGroup: pointer.Int64(0),
|
||||
},
|
||||
ImagePullSecrets: []corev1.LocalObjectReference{{
|
||||
Name: "pinniped-image-pull-secret",
|
||||
@@ -992,7 +992,7 @@ func TestAgentController(t *testing.T) {
|
||||
healthyAgentPod,
|
||||
validClusterInfoConfigMap,
|
||||
},
|
||||
discoveryURLOverride: pointer.StringPtr("https://overridden-server.example.com/some/path"),
|
||||
discoveryURLOverride: pointer.String("https://overridden-server.example.com/some/path"),
|
||||
mocks: mockExecSucceeds,
|
||||
wantDistinctErrors: []string{""},
|
||||
wantAgentDeployment: healthyAgentDeployment,
|
||||
|
||||
@@ -263,7 +263,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there are valid, expired authcode secrets which contain upstream refresh tokens", func() {
|
||||
it.Before(func() {
|
||||
activeOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: true,
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-1",
|
||||
@@ -308,7 +308,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
r.NoError(kubeClient.Tracker().Add(activeOIDCAuthcodeSessionSecret))
|
||||
|
||||
inactiveOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: false,
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-2",
|
||||
@@ -387,7 +387,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there are valid, expired authcode secrets which contain upstream access tokens", func() {
|
||||
it.Before(func() {
|
||||
activeOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: true,
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-1",
|
||||
@@ -432,7 +432,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
r.NoError(kubeClient.Tracker().Add(activeOIDCAuthcodeSessionSecret))
|
||||
|
||||
inactiveOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: false,
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-2",
|
||||
@@ -511,7 +511,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there is an invalid, expired authcode secret", func() {
|
||||
it.Before(func() {
|
||||
invalidOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: true,
|
||||
Request: &fosite.Request{
|
||||
ID: "", // it is invalid for there to be a missing request ID
|
||||
@@ -580,7 +580,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there is a valid, expired authcode secret but its upstream name does not match any existing upstream", func() {
|
||||
it.Before(func() {
|
||||
wrongProviderNameOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: true,
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-1",
|
||||
@@ -651,7 +651,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there is a valid, expired authcode secret but its upstream UID does not match any existing upstream", func() {
|
||||
it.Before(func() {
|
||||
wrongProviderNameOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: true,
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-1",
|
||||
@@ -722,7 +722,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there is a valid, recently expired authcode secret but the upstream revocation fails", func() {
|
||||
it.Before(func() {
|
||||
activeOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: true,
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-1",
|
||||
@@ -827,7 +827,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there is a valid, long-since expired authcode secret but the upstream revocation fails", func() {
|
||||
it.Before(func() {
|
||||
activeOIDCAuthcodeSession := &authorizationcode.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: true,
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-1",
|
||||
@@ -906,7 +906,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there are valid, expired access token secrets which contain upstream refresh tokens", func() {
|
||||
it.Before(func() {
|
||||
offlineAccessGrantedOIDCAccessTokenSession := &accesstoken.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Request: &fosite.Request{
|
||||
GrantedScope: fosite.Arguments{"scope1", "scope2", "offline_access"},
|
||||
ID: "request-id-1",
|
||||
@@ -951,7 +951,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
r.NoError(kubeClient.Tracker().Add(offlineAccessGrantedOIDCAccessTokenSessionSecret))
|
||||
|
||||
offlineAccessNotGrantedOIDCAccessTokenSession := &accesstoken.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Request: &fosite.Request{
|
||||
GrantedScope: fosite.Arguments{"scope1", "scope2"},
|
||||
ID: "request-id-2",
|
||||
@@ -1030,7 +1030,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there are valid, expired access token secrets which contain upstream access tokens", func() {
|
||||
it.Before(func() {
|
||||
offlineAccessGrantedOIDCAccessTokenSession := &accesstoken.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Request: &fosite.Request{
|
||||
GrantedScope: fosite.Arguments{"scope1", "scope2", "offline_access"},
|
||||
ID: "request-id-1",
|
||||
@@ -1075,7 +1075,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
r.NoError(kubeClient.Tracker().Add(offlineAccessGrantedOIDCAccessTokenSessionSecret))
|
||||
|
||||
offlineAccessNotGrantedOIDCAccessTokenSession := &accesstoken.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Request: &fosite.Request{
|
||||
GrantedScope: fosite.Arguments{"scope1", "scope2"},
|
||||
ID: "request-id-2",
|
||||
@@ -1154,7 +1154,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there are valid, expired refresh secrets which contain upstream refresh tokens", func() {
|
||||
it.Before(func() {
|
||||
oidcRefreshSession := &refreshtoken.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-1",
|
||||
Client: &clientregistry.Client{},
|
||||
@@ -1231,7 +1231,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
when("there are valid, expired refresh secrets which contain upstream access tokens", func() {
|
||||
it.Before(func() {
|
||||
oidcRefreshSession := &refreshtoken.Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Request: &fosite.Request{
|
||||
ID: "request-id-1",
|
||||
Client: &clientregistry.Client{},
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/compose"
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -42,7 +43,7 @@ func TestStorage(t *testing.T) {
|
||||
Tracker() coretesting.ObjectTracker
|
||||
}
|
||||
|
||||
hmac := compose.NewOAuth2HMACStrategy(&compose.Config{}, []byte("super-secret-32-byte-for-testing"), nil)
|
||||
hmac := compose.NewOAuth2HMACStrategy(&fosite.Config{GlobalSecret: []byte("super-secret-32-byte-for-testing")})
|
||||
// test data generation via:
|
||||
// code, signature, err := hmac.GenerateAuthorizeCode(ctx, nil)
|
||||
|
||||
@@ -117,7 +118,7 @@ func TestStorage(t *testing.T) {
|
||||
resource: "access-tokens",
|
||||
mocks: nil,
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode1)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode1)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -288,7 +289,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode1)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode1)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -424,7 +425,7 @@ func TestStorage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode2)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode2)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -493,7 +494,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -593,7 +594,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -672,7 +673,7 @@ func TestStorage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode2)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode2)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -934,7 +935,7 @@ func TestStorage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -998,7 +999,7 @@ func TestStorage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -1062,7 +1063,7 @@ func TestStorage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -1126,7 +1127,7 @@ func TestStorage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -1170,7 +1171,7 @@ func TestStorage(t *testing.T) {
|
||||
mocks: nil,
|
||||
lifetime: func() time.Duration { return 0 }, // 0 == infinity
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode1)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode1)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
@@ -1232,7 +1233,7 @@ func TestStorage(t *testing.T) {
|
||||
mocks: nil,
|
||||
lifetime: func() time.Duration { return 0 }, // 0 == infinity
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode1)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), authorizationCode1)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ const (
|
||||
// Version 1 was the initial release of storage.
|
||||
// Version 2 is when we switched to storing psession.PinnipedSession inside the fosite request.
|
||||
// Version 3 is when we added the Username field to the psession.CustomSessionData.
|
||||
accessTokenStorageVersion = "3"
|
||||
// Version 4 is when fosite added json tags to their openid.DefaultSession struct.
|
||||
accessTokenStorageVersion = "4"
|
||||
)
|
||||
|
||||
type RevocationStorage interface {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/handler/openid"
|
||||
"github.com/ory/fosite/token/jwt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -53,7 +54,7 @@ func TestAccessTokenStorage(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/access-token",
|
||||
@@ -122,7 +123,7 @@ func TestAccessTokenStorageRevocation(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/access-token",
|
||||
@@ -195,7 +196,7 @@ func TestWrongVersion(t *testing.T) {
|
||||
|
||||
_, err = storage.GetAccessTokenSession(ctx, "fancy-signature", nil)
|
||||
|
||||
require.EqualError(t, err, "access token request data has wrong version: access token session for fancy-signature has version not-the-right-version instead of 3")
|
||||
require.EqualError(t, err, "access token request data has wrong version: access token session for fancy-signature has version not-the-right-version instead of 4")
|
||||
}
|
||||
|
||||
func TestNilSessionRequest(t *testing.T) {
|
||||
@@ -213,7 +214,7 @@ func TestNilSessionRequest(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/access-token",
|
||||
@@ -297,13 +298,13 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"3","active": true}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"4","active": true}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/access-token",
|
||||
},
|
||||
wantSession: &Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Request: &fosite.Request{
|
||||
ID: "abcd-1",
|
||||
Client: &clientregistry.Client{},
|
||||
@@ -311,6 +312,8 @@ func TestReadFromSecret(t *testing.T) {
|
||||
Fosite: &openid.DefaultSession{
|
||||
Username: "snorlax",
|
||||
Subject: "panda",
|
||||
Claims: &jwt.IDTokenClaims{JTI: "xyz"},
|
||||
Headers: &jwt.Headers{Extra: map[string]interface{}{"myheader": "foo"}},
|
||||
},
|
||||
Custom: &psession.CustomSessionData{
|
||||
Username: "fake-username",
|
||||
@@ -359,7 +362,7 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
Type: "storage.pinniped.dev/access-token",
|
||||
},
|
||||
wantErr: "access token request data has wrong version: access token session has version wrong-version-here instead of 3",
|
||||
wantErr: "access token request data has wrong version: access token session has version wrong-version-here instead of 4",
|
||||
},
|
||||
{
|
||||
name: "missing request",
|
||||
@@ -372,7 +375,7 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"version":"3","active": true}`),
|
||||
"pinniped-storage-data": []byte(`{"version":"4","active": true}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/access-token",
|
||||
|
||||
@@ -31,7 +31,8 @@ const (
|
||||
// Version 1 was the initial release of storage.
|
||||
// Version 2 is when we switched to storing psession.PinnipedSession inside the fosite request.
|
||||
// Version 3 is when we added the Username field to the psession.CustomSessionData.
|
||||
authorizeCodeStorageVersion = "3"
|
||||
// Version 4 is when fosite added json tags to their openid.DefaultSession struct.
|
||||
authorizeCodeStorageVersion = "4"
|
||||
)
|
||||
|
||||
var _ oauth2.AuthorizeCodeStorage = &authorizeCodeStorage{}
|
||||
@@ -314,25 +315,25 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
||||
},
|
||||
"session": {
|
||||
"fosite": {
|
||||
"Claims": {
|
||||
"JTI": "褗6巽ēđų蓼tùZ蛆鬣a\"ÙǞ0觢",
|
||||
"Issuer": "j¦鲶H股ƲLŋZ-{",
|
||||
"Subject": "ehpƧ蓟",
|
||||
"Audience": [
|
||||
"id_token_claims": {
|
||||
"jti": "褗6巽ēđų蓼tùZ蛆鬣a\"ÙǞ0觢",
|
||||
"iss": "j¦鲶H股ƲLŋZ-{",
|
||||
"sub": "ehpƧ蓟",
|
||||
"aud": [
|
||||
"驜Ŗ~ů崧軒q腟u尿宲!"
|
||||
],
|
||||
"Nonce": "ǎ^嫯R忑隯ƗƋ*L\u0026",
|
||||
"ExpiresAt": "1989-06-02T14:40:29.613836765Z",
|
||||
"IssuedAt": "2052-03-26T02:39:27.882495556Z",
|
||||
"RequestedAt": "2038-04-06T10:46:24.698586972Z",
|
||||
"AuthTime": "2003-01-05T11:30:18.206004879Z",
|
||||
"AccessTokenHash": "ğǫ\\aȊ4ț髄Al",
|
||||
"AuthenticationContextClassReference": "曓蓳n匟鯘磹*金爃鶴滱ůĮǐ_c3#",
|
||||
"AuthenticationMethodsReferences": [
|
||||
"nonce": "ǎ^嫯R忑隯ƗƋ*L\u0026",
|
||||
"exp": "1989-06-02T14:40:29.613836765Z",
|
||||
"iat": "2052-03-26T02:39:27.882495556Z",
|
||||
"rat": "2038-04-06T10:46:24.698586972Z",
|
||||
"auth_time": "2003-01-05T11:30:18.206004879Z",
|
||||
"at_hash": "ğǫ\\aȊ4ț髄Al",
|
||||
"acr": "曓蓳n匟鯘磹*金爃鶴滱ůĮǐ_c3#",
|
||||
"amr": [
|
||||
"装ƹýĸŴB岺Ð嫹Sx镯荫őł疂ư墫"
|
||||
],
|
||||
"CodeHash": "\u0026鶡",
|
||||
"Extra": {
|
||||
"c_hash": "\u0026鶡",
|
||||
"ext": {
|
||||
"rǓ\\BRë_g\"ʎ啴SƇMǃļū": {
|
||||
"4撎胬龯,t猟i\u0026\u0026Q@ǤǟǗ": [
|
||||
1239190737
|
||||
@@ -347,8 +348,8 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
||||
"鑳绪": 2738428764
|
||||
}
|
||||
},
|
||||
"Headers": {
|
||||
"Extra": {
|
||||
"headers": {
|
||||
"extra": {
|
||||
"d謺錳4帳ŅǃĊ": 663773398,
|
||||
"Ř鸨EJ": {
|
||||
"Ǽǟ迍阊v\"豑觳翢砜": [
|
||||
@@ -363,11 +364,11 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"ExpiresAt": {
|
||||
"expires_at": {
|
||||
"韁臯氃妪婝rȤ\"h丬鎒ơ娻}ɼƟ": "1970-04-27T04:31:30.902468229Z"
|
||||
},
|
||||
"Username": "髉龳ǽÙ",
|
||||
"Subject": "\u0026¥潝邎Ȗ莅ŝǔ盕戙鵮碡ʯiŬŽ"
|
||||
"username": "髉龳ǽÙ",
|
||||
"subject": "\u0026¥潝邎Ȗ莅ŝǔ盕戙鵮碡ʯiŬŽ"
|
||||
},
|
||||
"custom": {
|
||||
"username": "Ĝ眧Ĭ",
|
||||
@@ -408,5 +409,5 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
||||
"筫MN\u0026錝D肁Ŷɽ蔒PR}Ųʓl{"
|
||||
]
|
||||
},
|
||||
"version": "3"
|
||||
"version": "4"
|
||||
}`
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/handler/oauth2"
|
||||
"github.com/ory/fosite/handler/openid"
|
||||
"github.com/ory/fosite/token/jwt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
@@ -65,7 +66,7 @@ func TestAuthorizationCodeStorage(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"active":true,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"active":true,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/authcode",
|
||||
@@ -85,7 +86,7 @@ func TestAuthorizationCodeStorage(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"active":false,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"active":false,"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/authcode",
|
||||
@@ -203,7 +204,7 @@ func TestWrongVersion(t *testing.T) {
|
||||
|
||||
_, err = storage.GetAuthorizeCodeSession(ctx, "fancy-signature", nil)
|
||||
|
||||
require.EqualError(t, err, "authorization request data has wrong version: authorization code session for fancy-signature has version not-the-right-version instead of 3")
|
||||
require.EqualError(t, err, "authorization request data has wrong version: authorization code session for fancy-signature has version not-the-right-version instead of 4")
|
||||
}
|
||||
|
||||
func TestNilSessionRequest(t *testing.T) {
|
||||
@@ -218,7 +219,7 @@ func TestNilSessionRequest(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value", "version":"3", "active": true}`),
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value", "version":"4", "active": true}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/authcode",
|
||||
@@ -385,7 +386,7 @@ func TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession(t *testing.T) {
|
||||
|
||||
// set these to match CreateAuthorizeCodeSession so that .JSONEq works
|
||||
validSession.Active = true
|
||||
validSession.Version = "3"
|
||||
validSession.Version = "4"
|
||||
|
||||
validSessionJSONBytes, err := json.MarshalIndent(validSession, "", "\t")
|
||||
require.NoError(t, err)
|
||||
@@ -420,13 +421,13 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"3","active": true}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"4","active": true}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/authcode",
|
||||
},
|
||||
wantSession: &Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Active: true,
|
||||
Request: &fosite.Request{
|
||||
ID: "abcd-1",
|
||||
@@ -435,6 +436,8 @@ func TestReadFromSecret(t *testing.T) {
|
||||
Fosite: &openid.DefaultSession{
|
||||
Username: "snorlax",
|
||||
Subject: "panda",
|
||||
Claims: &jwt.IDTokenClaims{JTI: "xyz"},
|
||||
Headers: &jwt.Headers{Extra: map[string]interface{}{"myheader": "foo"}},
|
||||
},
|
||||
Custom: &psession.CustomSessionData{
|
||||
Username: "fake-username",
|
||||
@@ -483,7 +486,7 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
Type: "storage.pinniped.dev/authcode",
|
||||
},
|
||||
wantErr: "authorization request data has wrong version: authorization code session has version wrong-version-here instead of 3",
|
||||
wantErr: "authorization request data has wrong version: authorization code session has version wrong-version-here instead of 4",
|
||||
},
|
||||
{
|
||||
name: "missing request",
|
||||
@@ -496,7 +499,7 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"version":"3","active": true}`),
|
||||
"pinniped-storage-data": []byte(`{"version":"4","active": true}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/authcode",
|
||||
|
||||
@@ -31,7 +31,8 @@ const (
|
||||
// Version 1 was the initial release of storage.
|
||||
// Version 2 is when we switched to storing psession.PinnipedSession inside the fosite request.
|
||||
// Version 3 is when we added the Username field to the psession.CustomSessionData.
|
||||
oidcStorageVersion = "3"
|
||||
// Version 4 is when fosite added json tags to their openid.DefaultSession struct.
|
||||
oidcStorageVersion = "4"
|
||||
)
|
||||
|
||||
var _ openid.OpenIDConnectRequestStorage = &openIDConnectRequestStorage{}
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestOpenIdConnectStorage(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/oidc",
|
||||
@@ -137,7 +137,7 @@ func TestWrongVersion(t *testing.T) {
|
||||
|
||||
_, err = storage.GetOpenIDConnectSession(ctx, "fancy-code.fancy-signature", nil)
|
||||
|
||||
require.EqualError(t, err, "oidc request data has wrong version: oidc session for fancy-signature has version not-the-right-version instead of 3")
|
||||
require.EqualError(t, err, "oidc request data has wrong version: oidc session for fancy-signature has version not-the-right-version instead of 4")
|
||||
}
|
||||
|
||||
func TestNilSessionRequest(t *testing.T) {
|
||||
@@ -152,7 +152,7 @@ func TestNilSessionRequest(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/oidc",
|
||||
|
||||
@@ -29,7 +29,8 @@ const (
|
||||
// Version 1 was the initial release of storage.
|
||||
// Version 2 is when we switched to storing psession.PinnipedSession inside the fosite request.
|
||||
// Version 3 is when we added the Username field to the psession.CustomSessionData.
|
||||
pkceStorageVersion = "3"
|
||||
// Version 4 is when fosite added json tags to their openid.DefaultSession struct.
|
||||
pkceStorageVersion = "4"
|
||||
)
|
||||
|
||||
var _ pkce.PKCERequestStorage = &pkceStorage{}
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestPKCEStorage(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/pkce",
|
||||
@@ -140,7 +140,7 @@ func TestWrongVersion(t *testing.T) {
|
||||
|
||||
_, err = storage.GetPKCERequestSession(ctx, "fancy-signature", nil)
|
||||
|
||||
require.EqualError(t, err, "pkce request data has wrong version: pkce session for fancy-signature has version not-the-right-version instead of 3")
|
||||
require.EqualError(t, err, "pkce request data has wrong version: pkce session for fancy-signature has version not-the-right-version instead of 4")
|
||||
}
|
||||
|
||||
func TestNilSessionRequest(t *testing.T) {
|
||||
@@ -158,7 +158,7 @@ func TestNilSessionRequest(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/pkce",
|
||||
|
||||
@@ -30,7 +30,8 @@ const (
|
||||
// Version 1 was the initial release of storage.
|
||||
// Version 2 is when we switched to storing psession.PinnipedSession inside the fosite request.
|
||||
// Version 3 is when we added the Username field to the psession.CustomSessionData.
|
||||
refreshTokenStorageVersion = "3"
|
||||
// Version 4 is when fosite added json tags to their openid.DefaultSession struct.
|
||||
refreshTokenStorageVersion = "4"
|
||||
)
|
||||
|
||||
type RevocationStorage interface {
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/handler/openid"
|
||||
"github.com/ory/fosite/token/jwt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -52,7 +53,7 @@ func TestRefreshTokenStorage(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/refresh-token",
|
||||
@@ -122,7 +123,7 @@ func TestRefreshTokenStorageRevocation(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/refresh-token",
|
||||
@@ -177,7 +178,7 @@ func TestRefreshTokenStorageRevokeRefreshTokenMaybeGracePeriod(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","requestedAt":"0001-01-01T00:00:00Z","client":{"id":"pinny","redirect_uris":null,"grant_types":null,"response_types":null,"scopes":null,"audience":null,"public":true,"jwks_uri":"where","jwks":null,"token_endpoint_auth_method":"something","request_uris":null,"request_object_signing_alg":"","token_endpoint_auth_signing_alg":""},"scopes":null,"grantedScopes":null,"form":{"key":["val"]},"session":{"fosite":{"id_token_claims":null,"headers":null,"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","warnings":null,"oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token","upstreamAccessToken":"","upstreamSubject":"some-subject","upstreamIssuer":"some-issuer"}}},"requestedAudience":null,"grantedAudience":null},"version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/refresh-token",
|
||||
@@ -251,7 +252,7 @@ func TestWrongVersion(t *testing.T) {
|
||||
|
||||
_, err = storage.GetRefreshTokenSession(ctx, "fancy-signature", nil)
|
||||
|
||||
require.EqualError(t, err, "refresh token request data has wrong version: refresh token session for fancy-signature has version not-the-right-version instead of 3")
|
||||
require.EqualError(t, err, "refresh token request data has wrong version: refresh token session for fancy-signature has version not-the-right-version instead of 4")
|
||||
}
|
||||
|
||||
func TestNilSessionRequest(t *testing.T) {
|
||||
@@ -269,7 +270,7 @@ func TestNilSessionRequest(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"3"}`),
|
||||
"pinniped-storage-data": []byte(`{"nonsense-key": "nonsense-value","version":"4"}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/refresh-token",
|
||||
@@ -353,13 +354,13 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"Claims":null,"Headers":null,"ExpiresAt":null,"Username":"snorlax","Subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"3","active": true}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1","session":{"fosite":{"id_token_claims":{"jti": "xyz"},"headers":{"extra":{"myheader": "foo"}},"expires_at":null,"username":"snorlax","subject":"panda"},"custom":{"username":"fake-username","providerUID":"fake-provider-uid","providerName":"fake-provider-name","providerType":"fake-provider-type","oidc":{"upstreamRefreshToken":"fake-upstream-refresh-token"}}}},"version":"4","active": true}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/refresh-token",
|
||||
},
|
||||
wantSession: &Session{
|
||||
Version: "3",
|
||||
Version: "4",
|
||||
Request: &fosite.Request{
|
||||
ID: "abcd-1",
|
||||
Client: &clientregistry.Client{},
|
||||
@@ -367,6 +368,8 @@ func TestReadFromSecret(t *testing.T) {
|
||||
Fosite: &openid.DefaultSession{
|
||||
Username: "snorlax",
|
||||
Subject: "panda",
|
||||
Claims: &jwt.IDTokenClaims{JTI: "xyz"},
|
||||
Headers: &jwt.Headers{Extra: map[string]interface{}{"myheader": "foo"}},
|
||||
},
|
||||
Custom: &psession.CustomSessionData{
|
||||
Username: "fake-username",
|
||||
@@ -392,7 +395,7 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"3","active": true}`),
|
||||
"pinniped-storage-data": []byte(`{"request":{"id":"abcd-1"},"version":"4","active": true}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/not-refresh-token",
|
||||
@@ -415,7 +418,7 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
Type: "storage.pinniped.dev/refresh-token",
|
||||
},
|
||||
wantErr: "refresh token request data has wrong version: refresh token session has version wrong-version-here instead of 3",
|
||||
wantErr: "refresh token request data has wrong version: refresh token session has version wrong-version-here instead of 4",
|
||||
},
|
||||
{
|
||||
name: "missing request",
|
||||
@@ -428,7 +431,7 @@ func TestReadFromSecret(t *testing.T) {
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"pinniped-storage-data": []byte(`{"version":"3","active": true}`),
|
||||
"pinniped-storage-data": []byte(`{"version":"4","active": true}`),
|
||||
"pinniped-storage-version": []byte("1"),
|
||||
},
|
||||
Type: "storage.pinniped.dev/refresh-token",
|
||||
|
||||
@@ -125,7 +125,7 @@ func handleAuthRequestForLDAPUpstreamCLIFlow(
|
||||
return nil
|
||||
}
|
||||
|
||||
if !requireStaticClientForUsernameAndPasswordHeaders(w, oauthHelper, authorizeRequester) {
|
||||
if !requireStaticClientForUsernameAndPasswordHeaders(r, w, oauthHelper, authorizeRequester) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ func handleAuthRequestForLDAPUpstreamCLIFlow(
|
||||
return httperr.New(http.StatusBadGateway, "unexpected error during upstream authentication")
|
||||
}
|
||||
if !authenticated {
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHintf("Username/password not accepted by LDAP provider."), true)
|
||||
return nil
|
||||
}
|
||||
@@ -203,7 +203,7 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
return nil
|
||||
}
|
||||
|
||||
if !requireStaticClientForUsernameAndPasswordHeaders(w, oauthHelper, authorizeRequester) {
|
||||
if !requireStaticClientForUsernameAndPasswordHeaders(r, w, oauthHelper, authorizeRequester) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
|
||||
if !oidcUpstream.AllowsPasswordGrant() {
|
||||
// Return a user-friendly error for this case which is entirely within our control.
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHint(
|
||||
"Resource owner password credentials grant is not allowed for this upstream provider according to its configuration."), true)
|
||||
return nil
|
||||
@@ -229,7 +229,7 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
// However, the exact response is undefined in the sense that there is no such thing as a password grant in
|
||||
// the OIDC spec, so we don't try too hard to read the upstream errors in this case. (E.g. Dex departs from the
|
||||
// spec and returns something other than an "invalid_grant" error for bad resource owner credentials.)
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithDebug(err.Error()), true) // WithDebug hides the error from the client
|
||||
return nil
|
||||
}
|
||||
@@ -237,7 +237,7 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
subject, username, groups, err := downstreamsession.GetDownstreamIdentityFromUpstreamIDToken(oidcUpstream, token.IDToken.Claims)
|
||||
if err != nil {
|
||||
// Return a user-friendly error for this case which is entirely within our control.
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHintf("Reason: %s.", err.Error()), true,
|
||||
)
|
||||
return nil
|
||||
@@ -245,7 +245,7 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
|
||||
customSessionData, err := downstreamsession.MakeDownstreamOIDCCustomSessionData(oidcUpstream, token, username)
|
||||
if err != nil {
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHintf("Reason: %s.", err.Error()), true,
|
||||
)
|
||||
return nil
|
||||
@@ -321,10 +321,10 @@ func handleAuthRequestForOIDCUpstreamBrowserFlow(
|
||||
return nil
|
||||
}
|
||||
|
||||
func requireStaticClientForUsernameAndPasswordHeaders(w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, authorizeRequester fosite.AuthorizeRequester) bool {
|
||||
func requireStaticClientForUsernameAndPasswordHeaders(r *http.Request, w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, authorizeRequester fosite.AuthorizeRequester) bool {
|
||||
isStaticClient := authorizeRequester.GetClient().GetID() == oidcapi.ClientIDPinnipedCLI
|
||||
if !isStaticClient {
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHintf("This client is not allowed to submit username or password headers to this endpoint."), true)
|
||||
}
|
||||
return isStaticClient
|
||||
@@ -334,7 +334,7 @@ func requireNonEmptyUsernameAndPasswordHeaders(r *http.Request, w http.ResponseW
|
||||
username := r.Header.Get(oidcapi.AuthorizeUsernameHeaderName)
|
||||
password := r.Header.Get(oidcapi.AuthorizePasswordHeaderName)
|
||||
if username == "" || password == "" {
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHintf("Missing or blank username or password."), true)
|
||||
return "", "", false
|
||||
}
|
||||
@@ -344,7 +344,7 @@ func requireNonEmptyUsernameAndPasswordHeaders(r *http.Request, w http.ResponseW
|
||||
func newAuthorizeRequest(r *http.Request, w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, isBrowserless bool) (fosite.AuthorizeRequester, bool) {
|
||||
authorizeRequester, err := oauthHelper.NewAuthorizeRequest(r.Context(), r)
|
||||
if err != nil {
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester, err, isBrowserless)
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester, err, isBrowserless)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ func handleBrowserFlowAuthRequest(
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester, err, false)
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester, err, false)
|
||||
return nil, nil // already wrote the error response, don't return error
|
||||
}
|
||||
|
||||
@@ -488,7 +488,7 @@ func handleBrowserFlowAuthRequest(
|
||||
|
||||
promptParam := r.Form.Get(promptParamName)
|
||||
if promptParam == promptParamNone && oidc.ScopeWasRequested(authorizeRequester, oidcapi.ScopeOpenID) {
|
||||
oidc.WriteAuthorizeError(w, oauthHelper, authorizeRequester, fosite.ErrLoginRequired, false)
|
||||
oidc.WriteAuthorizeError(r, w, oauthHelper, authorizeRequester, fosite.ErrLoginRequired, false)
|
||||
return nil, nil // already wrote the error response, don't return error
|
||||
}
|
||||
|
||||
|
||||
@@ -694,8 +694,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -716,8 +716,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
wantRedirectLocationRegexp: happyAuthcodeDownstreamRedirectLocationRegexp,
|
||||
@@ -737,8 +737,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithActiveDirectory(&upstreamActiveDirectoryIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
wantRedirectLocationRegexp: happyAuthcodeDownstreamRedirectLocationRegexp,
|
||||
@@ -928,8 +928,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: "/some/path",
|
||||
contentType: formContentType,
|
||||
body: encodeQuery(happyGetRequestQueryMap),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -952,8 +952,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: "/some/path",
|
||||
contentType: formContentType,
|
||||
body: encodeQuery(happyGetRequestQueryMap),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
wantRedirectLocationRegexp: happyAuthcodeDownstreamRedirectLocationRegexp,
|
||||
@@ -975,8 +975,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: "/some/path",
|
||||
contentType: formContentType,
|
||||
body: encodeQuery(happyGetRequestQueryMap),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
wantRedirectLocationRegexp: happyAuthcodeDownstreamRedirectLocationRegexp,
|
||||
@@ -1131,8 +1131,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{
|
||||
"redirect_uri": downstreamRedirectURIWithDifferentPort, // not the same port number that is registered for the client
|
||||
}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -1155,8 +1155,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{
|
||||
"redirect_uri": downstreamRedirectURIWithDifferentPort, // not the same port number that is registered for the client
|
||||
}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
wantRedirectLocationRegexp: downstreamRedirectURIWithDifferentPort + `\?code=([^&]+)&scope=openid\+username\+groups&state=` + happyState,
|
||||
@@ -1195,8 +1195,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(9*time.Hour))).WithUserInfoURL().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -1217,8 +1217,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(1*time.Hour))).WithUserInfoURL().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -1250,8 +1250,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithoutRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(9*time.Hour))).WithUserInfoURL().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -1272,8 +1272,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&erroringUpstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusBadGateway,
|
||||
wantContentType: htmlContentType,
|
||||
wantBodyString: "Bad Gateway: unexpected error during upstream authentication\n",
|
||||
@@ -1283,8 +1283,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithActiveDirectory(&erroringUpstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusBadGateway,
|
||||
wantContentType: htmlContentType,
|
||||
wantBodyString: "Bad Gateway: unexpected error during upstream authentication\n",
|
||||
@@ -1299,8 +1299,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr("wrong-password"),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String("wrong-password"),
|
||||
wantPasswordGrantCall: &expectedPasswordGrant{
|
||||
performedByUpstreamName: oidcPasswordGrantUpstreamName,
|
||||
args: &oidctestutil.PasswordCredentialsGrantAndValidateTokensArgs{
|
||||
@@ -1317,8 +1317,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr("wrong-password"),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String("wrong-password"),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithBadUsernamePasswordHintErrorQuery),
|
||||
@@ -1329,8 +1329,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithActiveDirectory(&upstreamActiveDirectoryIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr("wrong-password"),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String("wrong-password"),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithBadUsernamePasswordHintErrorQuery),
|
||||
@@ -1341,8 +1341,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr("wrong-username"),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String("wrong-username"),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithBadUsernamePasswordHintErrorQuery),
|
||||
@@ -1353,8 +1353,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithActiveDirectory(&upstreamActiveDirectoryIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr("wrong-username"),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String("wrong-username"),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithBadUsernamePasswordHintErrorQuery),
|
||||
@@ -1366,7 +1366,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: nil, // do not send header
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithMissingUsernamePasswordHintErrorQuery),
|
||||
@@ -1378,7 +1378,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: nil, // do not send header
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithMissingUsernamePasswordHintErrorQuery),
|
||||
@@ -1390,7 +1390,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: nil, // do not send header
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithMissingUsernamePasswordHintErrorQuery),
|
||||
@@ -1401,7 +1401,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: nil, // do not send header
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1413,7 +1413,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithActiveDirectory(&upstreamActiveDirectoryIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: nil, // do not send header
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1425,8 +1425,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithoutRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(9*time.Hour))).WithoutUserInfoURL().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1438,8 +1438,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithAccessToken(oidcUpstreamAccessToken, metav1.NewTime(time.Now().Add(9*time.Hour))).WithoutUserInfoURL().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1451,8 +1451,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithEmptyAccessToken().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1464,8 +1464,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithoutRefreshToken().WithoutAccessToken().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1477,8 +1477,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithoutRefreshToken().WithEmptyAccessToken().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1490,8 +1490,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().WithEmptyRefreshToken().WithoutAccessToken().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1503,7 +1503,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: nil, // do not send header
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -1515,8 +1515,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(upstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithPasswordGrantDisallowedHintErrorQuery),
|
||||
@@ -1528,8 +1528,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"client_id": dynamicClientID, "scope": testutil.AllDynamicClientScopesSpaceSep}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithUsernamePasswordHeadersDisallowedHintErrorQuery),
|
||||
@@ -1541,8 +1541,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"client_id": dynamicClientID, "scope": testutil.AllDynamicClientScopesSpaceSep}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithUsernamePasswordHeadersDisallowedHintErrorQuery),
|
||||
@@ -1554,8 +1554,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
kubeResources: addFullyCapableDynamicClientAndSecretToKubeResources,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"client_id": dynamicClientID, "scope": testutil.AllDynamicClientScopesSpaceSep}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeAccessDeniedWithUsernamePasswordHeadersDisallowedHintErrorQuery),
|
||||
@@ -1603,8 +1603,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{
|
||||
"redirect_uri": "http://127.0.0.1/does-not-match-what-is-configured-for-pinniped-cli-client",
|
||||
}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantContentType: jsonContentType,
|
||||
wantBodyJSON: fositeInvalidRedirectURIErrorBody,
|
||||
@@ -1616,8 +1616,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{
|
||||
"redirect_uri": "http://127.0.0.1/does-not-match-what-is-configured-for-pinniped-cli-client",
|
||||
}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantContentType: jsonContentType,
|
||||
wantBodyJSON: fositeInvalidRedirectURIErrorBody,
|
||||
@@ -1629,8 +1629,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{
|
||||
"redirect_uri": "http://127.0.0.1/does-not-match-what-is-configured-for-pinniped-cli-client",
|
||||
}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusBadRequest,
|
||||
wantContentType: jsonContentType,
|
||||
wantBodyJSON: fositeInvalidRedirectURIErrorBody,
|
||||
@@ -1654,8 +1654,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"client_id": "invalid-client"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantContentType: jsonContentType,
|
||||
wantBodyJSON: fositeInvalidClientErrorBody,
|
||||
@@ -1718,8 +1718,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"response_type": "unsupported"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeUnsupportedResponseTypeErrorQuery),
|
||||
@@ -1730,8 +1730,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"response_type": "unsupported"}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeUnsupportedResponseTypeErrorQuery),
|
||||
@@ -1767,8 +1767,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithActiveDirectory(&upstreamActiveDirectoryIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"response_type": "unsupported"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeUnsupportedResponseTypeErrorQuery),
|
||||
@@ -1835,8 +1835,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"scope": "openid profile email tuna"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidScopeErrorQuery),
|
||||
@@ -1876,8 +1876,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"scope": "openid tuna"}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidScopeErrorQuery),
|
||||
@@ -1888,8 +1888,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithActiveDirectory(&upstreamActiveDirectoryIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"scope": "openid tuna"}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidScopeErrorQuery),
|
||||
@@ -1931,8 +1931,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"response_type": ""}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingResponseTypeErrorQuery),
|
||||
@@ -1943,8 +1943,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"response_type": ""}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingResponseTypeErrorQuery),
|
||||
@@ -1976,8 +1976,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithActiveDirectory(&upstreamActiveDirectoryIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"response_type": ""}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingResponseTypeErrorQuery),
|
||||
@@ -2023,8 +2023,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"client_id": ""}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusUnauthorized,
|
||||
wantContentType: jsonContentType,
|
||||
wantBodyJSON: fositeInvalidClientErrorBody,
|
||||
@@ -2074,8 +2074,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge": ""}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2088,8 +2088,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge": ""}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingCodeChallengeErrorQuery),
|
||||
@@ -2132,8 +2132,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": "this-is-not-a-valid-pkce-alg"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2146,8 +2146,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": "this-is-not-a-valid-pkce-alg"}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidCodeChallengeErrorQuery),
|
||||
@@ -2190,8 +2190,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": "plain"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2204,8 +2204,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": "plain"}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingCodeChallengeMethodErrorQuery),
|
||||
@@ -2248,8 +2248,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": ""}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2262,8 +2262,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": ""}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingCodeChallengeMethodErrorQuery),
|
||||
@@ -2312,8 +2312,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"prompt": "none login"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2328,8 +2328,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"prompt": "none login"}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositePromptHasNoneAndOtherValueErrorQuery),
|
||||
@@ -2383,8 +2383,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
// The following prompt value is illegal when openid is requested, but note that openid is not requested.
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"prompt": "none login", "scope": "email"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2406,8 +2406,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
// The following prompt value is illegal when openid is requested, but note that openid is not requested.
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"prompt": "none login", "scope": "email"}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=username\+groups&state=` + happyState, // username and groups scopes were not requested, but are granted anyway for backwards compatibility
|
||||
@@ -2429,8 +2429,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2455,8 +2455,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2482,8 +2482,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2510,8 +2510,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2537,8 +2537,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2555,8 +2555,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2570,8 +2570,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2595,8 +2595,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2620,8 +2620,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2644,8 +2644,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2659,8 +2659,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: htmlContentType,
|
||||
@@ -2683,8 +2683,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2698,8 +2698,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2713,8 +2713,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2728,8 +2728,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2743,8 +2743,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2758,8 +2758,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2773,8 +2773,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2788,8 +2788,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2803,8 +2803,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2818,8 +2818,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2833,8 +2833,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
),
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantPasswordGrantCall: happyUpstreamPasswordGrantMockExpectation,
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
@@ -2877,8 +2877,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithOIDC(passwordGrantUpstreamOIDCIdentityProviderBuilder().Build()),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"state": "short"}),
|
||||
customUsernameHeader: pointer.StringPtr(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.StringPtr(oidcUpstreamPassword),
|
||||
customUsernameHeader: pointer.String(oidcUpstreamUsername),
|
||||
customPasswordHeader: pointer.String(oidcUpstreamPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidStateErrorQuery),
|
||||
@@ -2889,8 +2889,8 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
idps: oidctestutil.NewUpstreamIDPListerBuilder().WithLDAP(&upstreamLDAPIdentityProvider),
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"state": "short"}),
|
||||
customUsernameHeader: pointer.StringPtr(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.StringPtr(happyLDAPPassword),
|
||||
customUsernameHeader: pointer.String(happyLDAPUsername),
|
||||
customPasswordHeader: pointer.String(happyLDAPPassword),
|
||||
wantStatus: http.StatusFound,
|
||||
wantContentType: jsonContentType,
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidStateErrorQuery),
|
||||
|
||||
@@ -89,7 +89,7 @@ func NewHandler(
|
||||
return httperr.Wrap(http.StatusInternalServerError, "error while generating and saving authcode", err)
|
||||
}
|
||||
|
||||
oauthHelper.WriteAuthorizeResponse(w, authorizeRequester, authorizeResponder)
|
||||
oauthHelper.WriteAuthorizeResponse(r.Context(), w, authorizeRequester, authorizeResponder)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
63
internal/oidc/dynamic_global_secret_config.go
Normal file
63
internal/oidc/dynamic_global_secret_config.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hash"
|
||||
"time"
|
||||
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/compose"
|
||||
)
|
||||
|
||||
// DynamicGlobalSecretConfig is a wrapper around fosite.Config which allows us to always return dynamic secrets,
|
||||
// since those secrets can change at any time when they are loaded or reloaded by our controllers.
|
||||
type DynamicGlobalSecretConfig struct {
|
||||
fositeConfig *fosite.Config
|
||||
keyFunc func() []byte
|
||||
}
|
||||
|
||||
var _ compose.HMACSHAStrategyConfigurator = &DynamicGlobalSecretConfig{}
|
||||
|
||||
func NewDynamicGlobalSecretConfig(
|
||||
fositeConfig *fosite.Config,
|
||||
keyFunc func() []byte,
|
||||
) *DynamicGlobalSecretConfig {
|
||||
return &DynamicGlobalSecretConfig{
|
||||
fositeConfig: fositeConfig,
|
||||
keyFunc: keyFunc,
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DynamicGlobalSecretConfig) GetAccessTokenLifespan(ctx context.Context) time.Duration {
|
||||
return d.fositeConfig.GetAccessTokenLifespan(ctx)
|
||||
}
|
||||
|
||||
func (d *DynamicGlobalSecretConfig) GetRefreshTokenLifespan(ctx context.Context) time.Duration {
|
||||
return d.fositeConfig.GetRefreshTokenLifespan(ctx)
|
||||
}
|
||||
|
||||
func (d *DynamicGlobalSecretConfig) GetAuthorizeCodeLifespan(ctx context.Context) time.Duration {
|
||||
return d.fositeConfig.GetAuthorizeCodeLifespan(ctx)
|
||||
}
|
||||
|
||||
func (d *DynamicGlobalSecretConfig) GetTokenEntropy(ctx context.Context) int {
|
||||
return d.fositeConfig.GetTokenEntropy(ctx)
|
||||
}
|
||||
|
||||
func (d *DynamicGlobalSecretConfig) GetHMACHasher(ctx context.Context) func() hash.Hash {
|
||||
return d.fositeConfig.GetHMACHasher(ctx)
|
||||
}
|
||||
|
||||
func (d *DynamicGlobalSecretConfig) GetGlobalSecret(ctx context.Context) ([]byte, error) {
|
||||
// Always call keyFunc() without ever caching its value, because that is the whole point
|
||||
// of this type. We want the global secret to be dynamic.
|
||||
return d.keyFunc(), nil
|
||||
}
|
||||
|
||||
func (d *DynamicGlobalSecretConfig) GetRotatedGlobalSecrets(ctx context.Context) ([][]byte, error) {
|
||||
// We don't support having multiple global secrets yet, but when we do we will need to implement this.
|
||||
return nil, nil
|
||||
}
|
||||
@@ -14,9 +14,14 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
accessTokenPrefix = "pin_at_" // "Pinniped access token" abbreviated.
|
||||
refreshTokenPrefix = "pin_rt_" // "Pinniped refresh token" abbreviated.
|
||||
authcodePrefix = "pin_ac_" // "Pinniped authorization code" abbreviated.
|
||||
pinAccessTokenPrefix = "pin_at_" // "Pinniped access token" abbreviated.
|
||||
oryAccessTokenPrefix = "ory_at_"
|
||||
|
||||
pinRefreshTokenPrefix = "pin_rt_" // "Pinniped refresh token" abbreviated.
|
||||
oryRefreshTokenPrefix = "ory_rt_"
|
||||
|
||||
pinAuthcodePrefix = "pin_ac_" // "Pinniped authorization code" abbreviated.
|
||||
oryAuthcodePrefix = "ory_ac_"
|
||||
)
|
||||
|
||||
// dynamicOauth2HMACStrategy is an oauth2.CoreStrategy that can dynamically load an HMAC key to sign
|
||||
@@ -29,16 +34,18 @@ const (
|
||||
// FederationDomain has a valid signing key.
|
||||
//
|
||||
// Tokens start with a custom prefix to make them identifiable as tokens when seen by a user
|
||||
// out of context, such as when accidentally committed to a GitHub repo.
|
||||
// out of context, such as when accidentally committed to a GitHub repo. After we implemented the
|
||||
// custom prefix feature, fosite later added the same feature, but did not make the prefix customizable.
|
||||
// Therefore, this code has been updated to replace the fosite prefix with our custom prefix.
|
||||
type dynamicOauth2HMACStrategy struct {
|
||||
fositeConfig *compose.Config
|
||||
fositeConfig *fosite.Config
|
||||
keyFunc func() []byte
|
||||
}
|
||||
|
||||
var _ oauth2.CoreStrategy = &dynamicOauth2HMACStrategy{}
|
||||
|
||||
func newDynamicOauth2HMACStrategy(
|
||||
fositeConfig *compose.Config,
|
||||
fositeConfig *fosite.Config,
|
||||
keyFunc func() []byte,
|
||||
) *dynamicOauth2HMACStrategy {
|
||||
return &dynamicOauth2HMACStrategy{
|
||||
@@ -47,17 +54,26 @@ func newDynamicOauth2HMACStrategy(
|
||||
}
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) AccessTokenSignature(token string) string {
|
||||
return s.delegate().AccessTokenSignature(token)
|
||||
func replacePrefix(s, prefixToReplace, newPrefix string) string {
|
||||
return newPrefix + strings.TrimPrefix(s, prefixToReplace)
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) AccessTokenSignature(ctx context.Context, token string) string {
|
||||
return s.delegate().AccessTokenSignature(ctx, token)
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) GenerateAccessToken(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
) (token string, signature string, err error) {
|
||||
) (string, string, error) {
|
||||
token, sig, err := s.delegate().GenerateAccessToken(ctx, requester)
|
||||
if err == nil {
|
||||
token = accessTokenPrefix + token
|
||||
if !strings.HasPrefix(token, oryAccessTokenPrefix) {
|
||||
// This would only happen if fosite changed how it generates tokens. Defensive programming here.
|
||||
return "", "", errorsx.WithStack(fosite.ErrInvalidTokenFormat.
|
||||
WithDebugf("Generated token does not have expected prefix"))
|
||||
}
|
||||
token = replacePrefix(token, oryAccessTokenPrefix, pinAccessTokenPrefix)
|
||||
}
|
||||
return token, sig, err
|
||||
}
|
||||
@@ -66,25 +82,30 @@ func (s *dynamicOauth2HMACStrategy) ValidateAccessToken(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
token string,
|
||||
) (err error) {
|
||||
if !strings.HasPrefix(token, accessTokenPrefix) {
|
||||
) error {
|
||||
if !strings.HasPrefix(token, pinAccessTokenPrefix) {
|
||||
return errorsx.WithStack(fosite.ErrInvalidTokenFormat.
|
||||
WithDebugf("Access token did not have prefix %q", accessTokenPrefix))
|
||||
WithDebugf("Access token did not have prefix %q", pinAccessTokenPrefix))
|
||||
}
|
||||
return s.delegate().ValidateAccessToken(ctx, requester, token[len(accessTokenPrefix):])
|
||||
return s.delegate().ValidateAccessToken(ctx, requester, replacePrefix(token, pinAccessTokenPrefix, oryAccessTokenPrefix))
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) RefreshTokenSignature(token string) string {
|
||||
return s.delegate().RefreshTokenSignature(token)
|
||||
func (s *dynamicOauth2HMACStrategy) RefreshTokenSignature(ctx context.Context, token string) string {
|
||||
return s.delegate().RefreshTokenSignature(ctx, token)
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) GenerateRefreshToken(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
) (token string, signature string, err error) {
|
||||
) (string, string, error) {
|
||||
token, sig, err := s.delegate().GenerateRefreshToken(ctx, requester)
|
||||
if err == nil {
|
||||
token = refreshTokenPrefix + token
|
||||
if !strings.HasPrefix(token, oryRefreshTokenPrefix) {
|
||||
// This would only happen if fosite changed how it generates tokens. Defensive programming here.
|
||||
return "", "", errorsx.WithStack(fosite.ErrInvalidTokenFormat.
|
||||
WithDebugf("Generated token does not have expected prefix"))
|
||||
}
|
||||
token = replacePrefix(token, oryRefreshTokenPrefix, pinRefreshTokenPrefix)
|
||||
}
|
||||
return token, sig, err
|
||||
}
|
||||
@@ -93,25 +114,30 @@ func (s *dynamicOauth2HMACStrategy) ValidateRefreshToken(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
token string,
|
||||
) (err error) {
|
||||
if !strings.HasPrefix(token, refreshTokenPrefix) {
|
||||
) error {
|
||||
if !strings.HasPrefix(token, pinRefreshTokenPrefix) {
|
||||
return errorsx.WithStack(fosite.ErrInvalidTokenFormat.
|
||||
WithDebugf("Refresh token did not have prefix %q", refreshTokenPrefix))
|
||||
WithDebugf("Refresh token did not have prefix %q", pinRefreshTokenPrefix))
|
||||
}
|
||||
return s.delegate().ValidateRefreshToken(ctx, requester, token[len(refreshTokenPrefix):])
|
||||
return s.delegate().ValidateRefreshToken(ctx, requester, replacePrefix(token, pinRefreshTokenPrefix, oryRefreshTokenPrefix))
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) AuthorizeCodeSignature(token string) string {
|
||||
return s.delegate().AuthorizeCodeSignature(token)
|
||||
func (s *dynamicOauth2HMACStrategy) AuthorizeCodeSignature(ctx context.Context, token string) string {
|
||||
return s.delegate().AuthorizeCodeSignature(ctx, token)
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) GenerateAuthorizeCode(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
) (token string, signature string, err error) {
|
||||
) (string, string, error) {
|
||||
authcode, sig, err := s.delegate().GenerateAuthorizeCode(ctx, requester)
|
||||
if err == nil {
|
||||
authcode = authcodePrefix + authcode
|
||||
if !strings.HasPrefix(authcode, oryAuthcodePrefix) {
|
||||
// This would only happen if fosite changed how it generates tokens. Defensive programming here.
|
||||
return "", "", errorsx.WithStack(fosite.ErrInvalidTokenFormat.
|
||||
WithDebugf("Generated token does not have expected prefix"))
|
||||
}
|
||||
authcode = replacePrefix(authcode, oryAuthcodePrefix, pinAuthcodePrefix)
|
||||
}
|
||||
return authcode, sig, err
|
||||
}
|
||||
@@ -120,14 +146,14 @@ func (s *dynamicOauth2HMACStrategy) ValidateAuthorizeCode(
|
||||
ctx context.Context,
|
||||
requester fosite.Requester,
|
||||
token string,
|
||||
) (err error) {
|
||||
if !strings.HasPrefix(token, authcodePrefix) {
|
||||
) error {
|
||||
if !strings.HasPrefix(token, pinAuthcodePrefix) {
|
||||
return errorsx.WithStack(fosite.ErrInvalidTokenFormat.
|
||||
WithDebugf("Authorization code did not have prefix %q", authcodePrefix))
|
||||
WithDebugf("Authorization code did not have prefix %q", pinAuthcodePrefix))
|
||||
}
|
||||
return s.delegate().ValidateAuthorizeCode(ctx, requester, token[len(authcodePrefix):])
|
||||
return s.delegate().ValidateAuthorizeCode(ctx, requester, replacePrefix(token, pinAuthcodePrefix, oryAuthcodePrefix))
|
||||
}
|
||||
|
||||
func (s *dynamicOauth2HMACStrategy) delegate() *oauth2.HMACSHAStrategy {
|
||||
return compose.NewOAuth2HMACStrategy(s.fositeConfig, s.keyFunc(), nil)
|
||||
return compose.NewOAuth2HMACStrategy(NewDynamicGlobalSecretConfig(s.fositeConfig, s.keyFunc))
|
||||
}
|
||||
|
||||
@@ -11,20 +11,19 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/compose"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDynamicOauth2HMACStrategy_Signatures(t *testing.T) {
|
||||
s := &dynamicOauth2HMACStrategy{
|
||||
fositeConfig: &compose.Config{}, // defaults are good enough for this unit test
|
||||
keyFunc: func() []byte { return []byte("12345678901234567890123456789012") },
|
||||
}
|
||||
s := newDynamicOauth2HMACStrategy(
|
||||
&fosite.Config{}, // defaults are good enough for this unit test
|
||||
func() []byte { return []byte("12345678901234567890123456789012") }, // 32 character secret key
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
token string
|
||||
signatureFunc func(token string) (signature string)
|
||||
signatureFunc func(ctx context.Context, token string) (signature string)
|
||||
wantSignature string
|
||||
}{
|
||||
{
|
||||
@@ -52,21 +51,21 @@ func TestDynamicOauth2HMACStrategy_Signatures(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
require.Equal(t, tt.wantSignature, tt.signatureFunc(tt.token))
|
||||
require.Equal(t, tt.wantSignature, tt.signatureFunc(context.Background(), tt.token))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDynamicOauth2HMACStrategy_Generate(t *testing.T) {
|
||||
s := &dynamicOauth2HMACStrategy{
|
||||
fositeConfig: &compose.Config{}, // defaults are good enough for this unit test
|
||||
keyFunc: func() []byte { return []byte("12345678901234567890123456789012") }, // 32 character secret key
|
||||
}
|
||||
s := newDynamicOauth2HMACStrategy(
|
||||
&fosite.Config{}, // defaults are good enough for this unit test
|
||||
func() []byte { return []byte("12345678901234567890123456789012") }, // 32 character secret key
|
||||
)
|
||||
|
||||
generateTokenErrorCausingStrategy := &dynamicOauth2HMACStrategy{
|
||||
fositeConfig: &compose.Config{},
|
||||
keyFunc: func() []byte { return []byte("too_short_causes_error") }, // secret key is below required 32 characters
|
||||
}
|
||||
generateTokenErrorCausingStrategy := newDynamicOauth2HMACStrategy(
|
||||
&fosite.Config{},
|
||||
func() []byte { return []byte("too_short_causes_error") }, // secret key is below required 32 characters
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -135,10 +134,10 @@ func TestDynamicOauth2HMACStrategy_Generate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDynamicOauth2HMACStrategy_Validate(t *testing.T) {
|
||||
s := &dynamicOauth2HMACStrategy{
|
||||
fositeConfig: &compose.Config{}, // defaults are good enough for this unit test
|
||||
keyFunc: func() []byte { return []byte("12345678901234567890123456789012") },
|
||||
}
|
||||
s := newDynamicOauth2HMACStrategy(
|
||||
&fosite.Config{}, // defaults are good enough for this unit test
|
||||
func() []byte { return []byte("12345678901234567890123456789012") }, // 32 character secret key
|
||||
)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/compose"
|
||||
@@ -26,14 +27,14 @@ import (
|
||||
// could have an invariant that routes to an FederationDomain's endpoints are only wired up if an
|
||||
// FederationDomain has a valid signing key.
|
||||
type dynamicOpenIDConnectECDSAStrategy struct {
|
||||
fositeConfig *compose.Config
|
||||
fositeConfig *fosite.Config
|
||||
jwksProvider jwks.DynamicJWKSProvider
|
||||
}
|
||||
|
||||
var _ openid.OpenIDConnectTokenStrategy = &dynamicOpenIDConnectECDSAStrategy{}
|
||||
|
||||
func newDynamicOpenIDConnectECDSAStrategy(
|
||||
fositeConfig *compose.Config,
|
||||
fositeConfig *fosite.Config,
|
||||
jwksProvider jwks.DynamicJWKSProvider,
|
||||
) *dynamicOpenIDConnectECDSAStrategy {
|
||||
return &dynamicOpenIDConnectECDSAStrategy{
|
||||
@@ -44,6 +45,7 @@ func newDynamicOpenIDConnectECDSAStrategy(
|
||||
|
||||
func (s *dynamicOpenIDConnectECDSAStrategy) GenerateIDToken(
|
||||
ctx context.Context,
|
||||
lifespan time.Duration,
|
||||
requester fosite.Requester,
|
||||
) (string, error) {
|
||||
_, activeJwk := s.jwksProvider.GetJWKS(s.fositeConfig.IDTokenIssuer)
|
||||
@@ -67,5 +69,10 @@ func (s *dynamicOpenIDConnectECDSAStrategy) GenerateIDToken(
|
||||
return "", fosite.ErrServerError.WithWrap(constable.Error("JWK must be of type ecdsa"))
|
||||
}
|
||||
|
||||
return compose.NewOpenIDConnectECDSAStrategy(s.fositeConfig, key).GenerateIDToken(ctx, requester)
|
||||
keyGetter := func(context.Context) (interface{}, error) {
|
||||
return key, nil
|
||||
}
|
||||
strategy := compose.NewOpenIDConnectStrategy(keyGetter, s.fositeConfig)
|
||||
|
||||
return strategy.GenerateIDToken(ctx, lifespan, requester)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package oidc
|
||||
@@ -12,9 +12,9 @@ import (
|
||||
"errors"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/compose"
|
||||
"github.com/ory/fosite/handler/openid"
|
||||
"github.com/ory/fosite/token/jwt"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -95,7 +95,7 @@ func TestDynamicOpenIDConnectECDSAStrategy(t *testing.T) {
|
||||
test.jwksProvider(jwksProvider)
|
||||
}
|
||||
s := newDynamicOpenIDConnectECDSAStrategy(
|
||||
&compose.Config{IDTokenIssuer: test.issuer},
|
||||
&fosite.Config{IDTokenIssuer: test.issuer},
|
||||
jwksProvider,
|
||||
)
|
||||
|
||||
@@ -114,7 +114,7 @@ func TestDynamicOpenIDConnectECDSAStrategy(t *testing.T) {
|
||||
"nonce": {goodNonce},
|
||||
},
|
||||
}
|
||||
idToken, err := s.GenerateIDToken(context.Background(), requester)
|
||||
idToken, err := s.GenerateIDToken(context.Background(), 2*time.Hour, requester)
|
||||
if test.wantErrorType != nil {
|
||||
require.True(t, errors.Is(err, test.wantErrorType))
|
||||
require.EqualError(t, err.(*fosite.RFC6749Error).Cause(), test.wantErrorCause)
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
package oidc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/subtle"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/felixge/httpsnoop"
|
||||
@@ -195,7 +197,11 @@ func FositeOauth2Helper(
|
||||
jwksProvider jwks.DynamicJWKSProvider,
|
||||
timeoutsConfiguration TimeoutsConfiguration,
|
||||
) fosite.OAuth2Provider {
|
||||
oauthConfig := &compose.Config{
|
||||
isRedirectURISecureStrict := func(_ context.Context, uri *url.URL) bool {
|
||||
return fosite.IsRedirectURISecureStrict(uri)
|
||||
}
|
||||
|
||||
oauthConfig := &fosite.Config{
|
||||
IDTokenIssuer: issuer,
|
||||
|
||||
AuthorizeCodeLifespan: timeoutsConfiguration.AuthorizeCodeLifespan,
|
||||
@@ -217,10 +223,16 @@ func FositeOauth2Helper(
|
||||
MinParameterEntropy: fosite.MinParameterEntropy,
|
||||
|
||||
// do not allow custom scheme redirects, only https and http (on loopback)
|
||||
RedirectSecureChecker: fosite.IsRedirectURISecureStrict,
|
||||
RedirectSecureChecker: isRedirectURISecureStrict,
|
||||
|
||||
// html template for rendering the authorization response when the request has response_mode=form_post
|
||||
FormPostHTMLTemplate: formposthtml.Template(),
|
||||
|
||||
// defaults to using BCrypt when nil
|
||||
ClientSecretsHasher: nil,
|
||||
}
|
||||
|
||||
provider := compose.Compose(
|
||||
oAuth2Provider := compose.Compose(
|
||||
oauthConfig,
|
||||
oauthStore,
|
||||
&compose.CommonStrategy{
|
||||
@@ -228,7 +240,6 @@ func FositeOauth2Helper(
|
||||
CoreStrategy: newDynamicOauth2HMACStrategy(oauthConfig, hmacSecretOfLengthAtLeast32Func),
|
||||
OpenIDConnectTokenStrategy: newDynamicOpenIDConnectECDSAStrategy(oauthConfig, jwksProvider),
|
||||
},
|
||||
nil, // hasher, defaults to using BCrypt when nil. Used for hashing client secrets.
|
||||
compose.OAuth2AuthorizeExplicitFactory,
|
||||
compose.OAuth2RefreshTokenGrantFactory,
|
||||
compose.OpenIDConnectExplicitFactory,
|
||||
@@ -236,8 +247,8 @@ func FositeOauth2Helper(
|
||||
compose.OAuth2PKCEFactory,
|
||||
TokenExchangeFactory, // handle the "urn:ietf:params:oauth:grant-type:token-exchange" grant type
|
||||
)
|
||||
provider.(*fosite.Fosite).FormPostHTMLTemplate = formposthtml.Template()
|
||||
return provider
|
||||
|
||||
return oAuth2Provider
|
||||
}
|
||||
|
||||
// FositeErrorForLog generates a list of information about the provided Fosite error that can be
|
||||
@@ -403,7 +414,7 @@ func FindUpstreamIDPByNameAndType(
|
||||
|
||||
// WriteAuthorizeError writes an authorization error as it should be returned by the authorization endpoint and other
|
||||
// similar endpoints that are the end of the downstream authcode flow. Errors responses are written in the usual fosite style.
|
||||
func WriteAuthorizeError(w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, authorizeRequester fosite.AuthorizeRequester, err error, isBrowserless bool) {
|
||||
func WriteAuthorizeError(r *http.Request, w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, authorizeRequester fosite.AuthorizeRequester, err error, isBrowserless bool) {
|
||||
if plog.Enabled(plog.LevelTrace) {
|
||||
// When trace level logging is enabled, include the stack trace in the log message.
|
||||
keysAndValues := FositeErrorForLog(err)
|
||||
@@ -420,7 +431,7 @@ func WriteAuthorizeError(w http.ResponseWriter, oauthHelper fosite.OAuth2Provide
|
||||
w = rewriteStatusSeeOtherToStatusFoundForBrowserless(w)
|
||||
}
|
||||
// Return an error according to OIDC spec 3.1.2.6 (second paragraph).
|
||||
oauthHelper.WriteAuthorizeError(w, authorizeRequester, err)
|
||||
oauthHelper.WriteAuthorizeError(r.Context(), w, authorizeRequester, err)
|
||||
}
|
||||
|
||||
// PerformAuthcodeRedirect successfully completes a downstream login by creating a session and
|
||||
@@ -437,13 +448,13 @@ func PerformAuthcodeRedirect(
|
||||
authorizeResponder, err := oauthHelper.NewAuthorizeResponse(r.Context(), authorizeRequester, openIDSession)
|
||||
if err != nil {
|
||||
plog.WarningErr("error while generating and saving authcode", err, "fositeErr", FositeErrorForLog(err))
|
||||
WriteAuthorizeError(w, oauthHelper, authorizeRequester, err, isBrowserless)
|
||||
WriteAuthorizeError(r, w, oauthHelper, authorizeRequester, err, isBrowserless)
|
||||
return
|
||||
}
|
||||
if isBrowserless {
|
||||
w = rewriteStatusSeeOtherToStatusFoundForBrowserless(w)
|
||||
}
|
||||
oauthHelper.WriteAuthorizeResponse(w, authorizeRequester, authorizeResponder)
|
||||
oauthHelper.WriteAuthorizeResponse(r.Context(), w, authorizeRequester, authorizeResponder)
|
||||
}
|
||||
|
||||
func rewriteStatusSeeOtherToStatusFoundForBrowserless(w http.ResponseWriter) http.ResponseWriter {
|
||||
|
||||
@@ -35,7 +35,7 @@ func NewHandler(
|
||||
accessRequest, err := oauthHelper.NewAccessRequest(r.Context(), r, session)
|
||||
if err != nil {
|
||||
plog.Info("token request error", oidc.FositeErrorForLog(err)...)
|
||||
oauthHelper.WriteAccessError(w, accessRequest, err)
|
||||
oauthHelper.WriteAccessError(r.Context(), w, accessRequest, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func NewHandler(
|
||||
err = upstreamRefresh(r.Context(), accessRequest, idpLister)
|
||||
if err != nil {
|
||||
plog.Info("upstream refresh error", oidc.FositeErrorForLog(err)...)
|
||||
oauthHelper.WriteAccessError(w, accessRequest, err)
|
||||
oauthHelper.WriteAccessError(r.Context(), w, accessRequest, err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -68,11 +68,11 @@ func NewHandler(
|
||||
accessResponse, err := oauthHelper.NewAccessResponse(r.Context(), accessRequest)
|
||||
if err != nil {
|
||||
plog.Info("token response error", oidc.FositeErrorForLog(err)...)
|
||||
oauthHelper.WriteAccessError(w, accessRequest, err)
|
||||
oauthHelper.WriteAccessError(r.Context(), w, accessRequest, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
oauthHelper.WriteAccessResponse(w, accessRequest, accessResponse)
|
||||
oauthHelper.WriteAccessResponse(r.Context(), w, accessRequest, accessResponse)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -1433,6 +1433,7 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn
|
||||
// at and expires at dates which are newer than the old tokens.
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
approxRequestTime := time.Now()
|
||||
subject.ServeHTTP(rsp, req)
|
||||
t.Logf("response: %#v", rsp)
|
||||
t.Logf("response body: %q", rsp.Body.String())
|
||||
@@ -1518,6 +1519,16 @@ func TestTokenEndpointTokenExchange(t *testing.T) { // tests for grant_type "urn
|
||||
requireClaimsAreNotEqual(t, "iat", claimsOfFirstIDToken, tokenClaims) // issued at
|
||||
require.Greater(t, tokenClaims["iat"], claimsOfFirstIDToken["iat"])
|
||||
|
||||
// Assert that the timestamps in the token are approximately as expected.
|
||||
expiresAtAsFloat, ok := tokenClaims["exp"].(float64)
|
||||
require.True(t, ok, "expected exp claim to be a float64")
|
||||
expiresAt := time.Unix(int64(expiresAtAsFloat), 0)
|
||||
testutil.RequireTimeInDelta(t, approxRequestTime.UTC().Add(idTokenExpirationSeconds*time.Second), expiresAt, timeComparisonFudge)
|
||||
issuedAtAsFloat, ok := tokenClaims["iat"].(float64)
|
||||
require.True(t, ok, "expected iat claim to be a float64")
|
||||
issuedAt := time.Unix(int64(issuedAtAsFloat), 0)
|
||||
testutil.RequireTimeInDelta(t, approxRequestTime.UTC(), issuedAt, timeComparisonFudge)
|
||||
|
||||
// Assert that nothing in storage has been modified.
|
||||
newSecrets, err := secrets.List(context.Background(), metav1.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
@@ -3735,8 +3746,6 @@ func TestRefreshGrant(t *testing.T) {
|
||||
require.Len(t, reqContextWarningRecorder.Warnings, 0, "wanted no warnings on the request context, but found some")
|
||||
}
|
||||
|
||||
// The bug in fosite that prevents at_hash from appearing in the initial ID token does not impact the refreshed ID token
|
||||
wantAtHashClaimInIDToken := true
|
||||
// Refreshed ID tokens do not include the nonce from the original auth request
|
||||
wantNonceValueInIDToken := false
|
||||
|
||||
@@ -3745,7 +3754,6 @@ func TestRefreshGrant(t *testing.T) {
|
||||
test.authcodeExchange.want.wantUsername, // the old username from the initial login
|
||||
test.authcodeExchange.want.wantGroups, // the old groups from the initial login
|
||||
test.authcodeExchange.customSessionData, // the old custom session data from the initial login
|
||||
wantAtHashClaimInIDToken,
|
||||
wantNonceValueInIDToken,
|
||||
refreshResponse,
|
||||
authCode,
|
||||
@@ -3784,8 +3792,9 @@ func TestRefreshGrant(t *testing.T) {
|
||||
err = secondIDTokenDecoded.UnsafeClaimsWithoutVerification(&claimsOfSecondIDToken)
|
||||
require.NoError(t, err)
|
||||
|
||||
requireClaimsAreNotEqual(t, "jti", claimsOfFirstIDToken, claimsOfSecondIDToken) // JWT ID
|
||||
requireClaimsAreNotEqual(t, "exp", claimsOfFirstIDToken, claimsOfSecondIDToken) // expires at
|
||||
requireClaimsAreNotEqual(t, "jti", claimsOfFirstIDToken, claimsOfSecondIDToken) // JWT ID
|
||||
requireClaimsAreNotEqual(t, "at_hash", claimsOfFirstIDToken, claimsOfSecondIDToken) // access token hash
|
||||
requireClaimsAreNotEqual(t, "exp", claimsOfFirstIDToken, claimsOfSecondIDToken) // expires at
|
||||
require.Greater(t, claimsOfSecondIDToken["exp"], claimsOfFirstIDToken["exp"])
|
||||
requireClaimsAreNotEqual(t, "iat", claimsOfFirstIDToken, claimsOfSecondIDToken) // issued at
|
||||
require.Greater(t, claimsOfSecondIDToken["iat"], claimsOfFirstIDToken["iat"])
|
||||
@@ -3880,15 +3889,13 @@ func exchangeAuthcodeForTokens(
|
||||
t.Logf("response: %#v", rsp)
|
||||
t.Logf("response body: %q", rsp.Body.String())
|
||||
|
||||
wantAtHashClaimInIDToken := false // due to a bug in fosite, the at_hash claim is not filled in during authcode exchange
|
||||
wantNonceValueInIDToken := true // ID tokens returned by the authcode exchange must include the nonce from the auth request (unlike refreshed ID tokens)
|
||||
wantNonceValueInIDToken := true // ID tokens returned by the authcode exchange must include the nonce from the auth request (unlike refreshed ID tokens)
|
||||
|
||||
requireTokenEndpointBehavior(t,
|
||||
test.want,
|
||||
test.want.wantUsername, // the old username from the initial login
|
||||
test.want.wantGroups, // the old groups from the initial login
|
||||
test.customSessionData, // the old custom session data from the initial login
|
||||
wantAtHashClaimInIDToken,
|
||||
wantNonceValueInIDToken,
|
||||
rsp,
|
||||
authCode,
|
||||
@@ -3907,7 +3914,6 @@ func requireTokenEndpointBehavior(
|
||||
oldUsername string,
|
||||
oldGroups []string,
|
||||
oldCustomSessionData *psession.CustomSessionData,
|
||||
wantAtHashClaimInIDToken bool,
|
||||
wantNonceValueInIDToken bool,
|
||||
tokenEndpointResponse *httptest.ResponseRecorder,
|
||||
authCode string,
|
||||
@@ -3942,7 +3948,7 @@ func requireTokenEndpointBehavior(
|
||||
expectedNumberOfIDSessionsStored := 0
|
||||
if wantIDToken {
|
||||
expectedNumberOfIDSessionsStored = 1
|
||||
requireValidIDToken(t, parsedResponseBody, jwtSigningKey, test.wantClientID, wantAtHashClaimInIDToken, wantNonceValueInIDToken, test.wantUsername, test.wantGroups, parsedResponseBody["access_token"].(string), requestTime)
|
||||
requireValidIDToken(t, parsedResponseBody, jwtSigningKey, test.wantClientID, wantNonceValueInIDToken, test.wantUsername, test.wantGroups, parsedResponseBody["access_token"].(string), requestTime)
|
||||
}
|
||||
if wantRefreshToken {
|
||||
requireValidRefreshTokenStorage(t, parsedResponseBody, oauthStore, test.wantClientID, test.wantRequestedScopes, test.wantGrantedScopes, test.wantUsername, test.wantGroups, test.wantCustomSessionDataStored, secrets, requestTime)
|
||||
@@ -4509,7 +4515,6 @@ func requireValidIDToken(
|
||||
body map[string]interface{},
|
||||
jwtSigningKey *ecdsa.PrivateKey,
|
||||
wantClientID string,
|
||||
wantAtHashClaimInIDToken bool,
|
||||
wantNonceValueInIDToken bool,
|
||||
wantUsernameInIDToken string,
|
||||
wantGroupsInIDToken []string,
|
||||
@@ -4541,13 +4546,7 @@ func requireValidIDToken(
|
||||
Username string `json:"username"`
|
||||
}
|
||||
|
||||
// Note that there is a bug in fosite which prevents the `at_hash` claim from appearing in this ID token
|
||||
// during the initial authcode exchange, but does not prevent `at_hash` from appearing in the refreshed ID token.
|
||||
// We can add a workaround for this later.
|
||||
idTokenFields := []string{"sub", "aud", "iss", "jti", "auth_time", "exp", "iat", "rat", "azp"}
|
||||
if wantAtHashClaimInIDToken {
|
||||
idTokenFields = append(idTokenFields, "at_hash")
|
||||
}
|
||||
idTokenFields := []string{"sub", "aud", "iss", "jti", "auth_time", "exp", "iat", "rat", "azp", "at_hash"}
|
||||
if wantNonceValueInIDToken {
|
||||
idTokenFields = append(idTokenFields, "nonce")
|
||||
}
|
||||
@@ -4590,12 +4589,8 @@ func requireValidIDToken(
|
||||
testutil.RequireTimeInDelta(t, goodRequestedAtTime, requestedAt, timeComparisonFudge)
|
||||
testutil.RequireTimeInDelta(t, goodAuthTime, authTime, timeComparisonFudge)
|
||||
|
||||
if wantAtHashClaimInIDToken {
|
||||
require.NotEmpty(t, actualAccessToken)
|
||||
require.Equal(t, hashAccessToken(actualAccessToken), claims.AccessTokenHash)
|
||||
} else {
|
||||
require.Empty(t, claims.AccessTokenHash)
|
||||
}
|
||||
require.NotEmpty(t, actualAccessToken)
|
||||
require.Equal(t, hashAccessToken(actualAccessToken), claims.AccessTokenHash)
|
||||
}
|
||||
|
||||
func deepCopyRequestForm(r *http.Request) *http.Request {
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/compose"
|
||||
"github.com/ory/fosite/handler/oauth2"
|
||||
"github.com/ory/fosite/handler/openid"
|
||||
"github.com/pkg/errors"
|
||||
@@ -28,11 +27,12 @@ type stsParams struct {
|
||||
requestedAudience string
|
||||
}
|
||||
|
||||
func TokenExchangeFactory(config *compose.Config, storage interface{}, strategy interface{}) interface{} {
|
||||
func TokenExchangeFactory(config fosite.Configurator, storage interface{}, strategy interface{}) interface{} {
|
||||
return &TokenExchangeHandler{
|
||||
idTokenStrategy: strategy.(openid.OpenIDConnectTokenStrategy),
|
||||
accessTokenStrategy: strategy.(oauth2.AccessTokenStrategy),
|
||||
accessTokenStorage: storage.(oauth2.AccessTokenStorage),
|
||||
fositeConfig: config,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,12 +40,13 @@ type TokenExchangeHandler struct {
|
||||
idTokenStrategy openid.OpenIDConnectTokenStrategy
|
||||
accessTokenStrategy oauth2.AccessTokenStrategy
|
||||
accessTokenStorage oauth2.AccessTokenStorage
|
||||
fositeConfig fosite.Configurator
|
||||
}
|
||||
|
||||
var _ fosite.TokenEndpointHandler = (*TokenExchangeHandler)(nil)
|
||||
|
||||
func (t *TokenExchangeHandler) HandleTokenEndpointRequest(ctx context.Context, requester fosite.AccessRequester) error {
|
||||
if !t.CanHandleTokenEndpointRequest(requester) {
|
||||
if !t.CanHandleTokenEndpointRequest(ctx, requester) {
|
||||
return errors.WithStack(fosite.ErrUnknownRequest)
|
||||
}
|
||||
return nil
|
||||
@@ -110,7 +111,12 @@ func (t *TokenExchangeHandler) PopulateTokenEndpointResponse(ctx context.Context
|
||||
func (t *TokenExchangeHandler) mintJWT(ctx context.Context, requester fosite.Requester, audience string) (string, error) {
|
||||
downscoped := fosite.NewAccessRequest(requester.GetSession())
|
||||
downscoped.Client.(*fosite.DefaultClient).ID = audience
|
||||
return t.idTokenStrategy.GenerateIDToken(ctx, downscoped)
|
||||
|
||||
// Note: if we wanted to support clients with custom token lifespans, then we would need to call
|
||||
// fosite.GetEffectiveLifespan() to determine the lifespan here.
|
||||
idTokenLifespan := t.fositeConfig.GetIDTokenLifespan(ctx)
|
||||
|
||||
return t.idTokenStrategy.GenerateIDToken(ctx, idTokenLifespan, downscoped)
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) validateSession(requester fosite.Requester) error {
|
||||
@@ -185,7 +191,7 @@ func (t *TokenExchangeHandler) validateParams(params url.Values) (*stsParams, er
|
||||
|
||||
func (t *TokenExchangeHandler) validateAccessToken(ctx context.Context, requester fosite.AccessRequester, accessToken string) (fosite.Requester, error) {
|
||||
// Look up the access token's stored session data.
|
||||
signature := t.accessTokenStrategy.AccessTokenSignature(accessToken)
|
||||
signature := t.accessTokenStrategy.AccessTokenSignature(ctx, accessToken)
|
||||
originalRequester, err := t.accessTokenStorage.GetAccessTokenSession(ctx, signature, requester.GetSession())
|
||||
if err != nil {
|
||||
// The access token was not found, or there was some other error while reading it.
|
||||
@@ -198,10 +204,10 @@ func (t *TokenExchangeHandler) validateAccessToken(ctx context.Context, requeste
|
||||
return originalRequester, nil
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) CanSkipClientAuth(_ fosite.AccessRequester) bool {
|
||||
func (t *TokenExchangeHandler) CanSkipClientAuth(_ context.Context, _ fosite.AccessRequester) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *TokenExchangeHandler) CanHandleTokenEndpointRequest(requester fosite.AccessRequester) bool {
|
||||
func (t *TokenExchangeHandler) CanHandleTokenEndpointRequest(_ context.Context, requester fosite.AccessRequester) bool {
|
||||
return requester.GetGrantTypes().ExactOne(oidcapi.GrantTypeTokenExchange)
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ const (
|
||||
|
||||
ErrOIDCClientSecretStorageVersion = constable.Error("OIDC client secret storage data has wrong version")
|
||||
|
||||
// Version 1 was the initial release of the OIDCClientSecretRequest API, which uses OIDCClientSecretStorage for storage.
|
||||
oidcClientSecretStorageVersion = "1"
|
||||
)
|
||||
|
||||
|
||||
@@ -386,7 +386,7 @@ func requireSuccessfulResponseWithAuthenticationFailureMessage(t *testing.T, err
|
||||
require.Equal(t, response, &loginapi.TokenCredentialRequest{
|
||||
Status: loginapi.TokenCredentialRequestStatus{
|
||||
Credential: nil,
|
||||
Message: pointer.StringPtr("authentication failed"),
|
||||
Message: pointer.String("authentication failed"),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ params:
|
||||
github_url: "https://github.com/vmware-tanzu/pinniped"
|
||||
slack_url: "https://go.pinniped.dev/community/slack"
|
||||
community_url: "https://go.pinniped.dev/community"
|
||||
latest_version: v0.19.0
|
||||
latest_version: v0.20.0
|
||||
latest_codegen_version: 1.25
|
||||
pygmentsCodefences: true
|
||||
pygmentsStyle: "pygments"
|
||||
|
||||
@@ -106,7 +106,7 @@ spec:
|
||||
# Specify how to filter the search to find the specific user by username.
|
||||
# "{}" will be replaced # by the username that the end-user had typed
|
||||
# when they tried to log in.
|
||||
filter: "&(objectClass=person)(userPrincipleName={})"
|
||||
filter: "&(objectClass=person)(userPrincipalName={})"
|
||||
|
||||
# Specify which fields from the user entry should be used upon
|
||||
# successful login.
|
||||
|
||||
@@ -194,7 +194,7 @@ pinniped get kubeconfig [flags]
|
||||
--oidc-issuer string OpenID Connect issuer URL (default: autodiscover)
|
||||
--oidc-listen-port uint16 TCP port for localhost listener (authorization code flow only)
|
||||
--oidc-request-audience string Request a token with an alternate audience using RFC8693 token exchange
|
||||
--oidc-scopes strings OpenID Connect scopes to request during login (default [offline_access,openid,pinniped:request-audience])
|
||||
--oidc-scopes strings OpenID Connect scopes to request during login (default [offline_access,openid,pinniped:request-audience,username,groups])
|
||||
--oidc-session-cache string Path to OpenID Connect session cache file
|
||||
--oidc-skip-browser During OpenID Connect login, skip opening the browser (just print the URL)
|
||||
-o, --output string Output file path (default: stdout)
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,57 +3,114 @@
|
||||
@import 'base';
|
||||
|
||||
footer {
|
||||
.left-links {
|
||||
padding: 0px;
|
||||
float: left;
|
||||
li {
|
||||
img {
|
||||
vertical-align: bottom;
|
||||
margin-right: 10px;
|
||||
}
|
||||
a {
|
||||
color: $grey;
|
||||
font-weight: 300;
|
||||
font-size: 12px;
|
||||
font-family: $metropolis-light;
|
||||
}
|
||||
.wrapper {
|
||||
padding: 20px;
|
||||
}
|
||||
li {
|
||||
list-style-type: none;
|
||||
display: inline;
|
||||
padding-right: 25px;
|
||||
font-size: 12px;
|
||||
&:last-of-type {
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
.right-links {
|
||||
float: right;
|
||||
p {
|
||||
margin: 0px;
|
||||
}
|
||||
.copywrite {
|
||||
font-size: 12px;
|
||||
padding-right: 10px;
|
||||
a {
|
||||
font-size: 12px;
|
||||
color: $grey;
|
||||
font-family: $metropolis-light;
|
||||
}
|
||||
.top-links {
|
||||
min-height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.left-links {
|
||||
padding: 0px;
|
||||
li {
|
||||
img {
|
||||
vertical-align: bottom;
|
||||
margin-right: 10px;
|
||||
}
|
||||
a {
|
||||
vertical-align: middle;
|
||||
color: $darkgrey;
|
||||
font-weight: 300;
|
||||
font-size: 12px;
|
||||
font-family: $metropolis-light;
|
||||
}
|
||||
}
|
||||
.mobile {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.right-links {
|
||||
p {
|
||||
margin: 0px;
|
||||
}
|
||||
.copywrite {
|
||||
font-size: 12px;
|
||||
padding-right: 10px;
|
||||
a {
|
||||
font-size: 12px;
|
||||
color: $grey;
|
||||
font-family: $metropolis-light;
|
||||
}
|
||||
}
|
||||
a {
|
||||
vertical-align: middle;
|
||||
}
|
||||
#vm-logo {
|
||||
// margin-left: 20px;
|
||||
// max-width: 100px;
|
||||
// margin-top: 5px;
|
||||
}
|
||||
}
|
||||
.bottom-links {
|
||||
margin: 10px 0px 30px 0px;
|
||||
p {
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
.ot-sdk-show-settings {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
a {
|
||||
font-size: 12px;
|
||||
font-family: $metropolis-light;
|
||||
}
|
||||
img {
|
||||
max-width: 75px;
|
||||
vertical-align: middle;
|
||||
margin-left: 30px;
|
||||
}
|
||||
}
|
||||
@include breakpoint(small) {
|
||||
.left-links {
|
||||
width: 100%;
|
||||
float: none;
|
||||
li {
|
||||
display: block;
|
||||
width: 33%;
|
||||
float: left;
|
||||
padding-right: 0px;
|
||||
}
|
||||
}
|
||||
.footer-links {
|
||||
display: block;
|
||||
.right-links {
|
||||
width: 100%;
|
||||
padding-top: 20px;
|
||||
.image {
|
||||
display: none;
|
||||
}
|
||||
display: none;
|
||||
}
|
||||
.left-links {
|
||||
float: none;
|
||||
margin: 10px 0px;
|
||||
.desktop {
|
||||
display: none;
|
||||
}
|
||||
.mobile {
|
||||
display: inline;
|
||||
}
|
||||
.copywrite {
|
||||
display: block;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.bottom-links {
|
||||
margin: 10px 0px 20px 0px;
|
||||
float: none;
|
||||
img {
|
||||
margin-left: 0px;
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,34 @@
|
||||
<footer>
|
||||
<div class="wrapper footer-links clearfix">
|
||||
<ul class="left-links">
|
||||
<li><a href="{{ .Site.Params.twitter_url }}"><img src="/img/twitter.png" alt="Twitter logo"/>Twitter</a></li>
|
||||
<li><a href="{{ .Site.Params.github_url }}"><img src="/img/github.svg" alt="GitHub logo" />GitHub</a></li>
|
||||
<li><a href="{{ .Site.Params.slack_url }}"><img src="/img/slack.png" alt="Slack logo" />Slack</a></li>
|
||||
</ul>
|
||||
<div class="right-links">
|
||||
<p><span class="copywrite">© {{ now.Year }} Pinniped Authors, A <a href="http://vmware.github.io/">VMware-backed project</a>.</span> <a class="image" href="/"> <img src="/img/logo.svg" alt="Pinniped logo" /></a></p>
|
||||
<div class="wrapper footer-links">
|
||||
<div class="top-links">
|
||||
<ul class="left-links">
|
||||
<li><a href="{{ .Site.Params.twitter_url }}" target="_blank"><img src="/img/twitter.png" />Twitter</a></li>
|
||||
<li><a href="{{ .Site.Params.github_url }}" target="_blank"><img src="/img/github.svg" />GitHub</a></li>
|
||||
<li><a href="{{ .Site.Params.slack_url }}" target="_blank"><img src="/img/slack.png" /><span class="desktop">Slack</span><span class="mobile">Slack</span></a></li>
|
||||
</ul>
|
||||
<div class="right-links">
|
||||
<p>
|
||||
</span> <a class="image" href="/"> <img src="/img/logo.svg" alt="Pinniped logo" /></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-links">
|
||||
<p>
|
||||
<span>
|
||||
© {{ now.Year }} Pinniped Authors. Apache 2.0 License.
|
||||
<a target="_blank" rel="noopener" href="https://github.com/vmware/">A VMware-backed project.</a>
|
||||
</span>
|
||||
<span>
|
||||
<a target="_blank" rel="noopener" href='https://www.vmware.com/help/legal.html'>Terms of Use</a> |
|
||||
<a target="_blank" rel="noopener" href='https://www.vmware.com/help/privacy.html'>Privacy Policy</a> |
|
||||
<a target="_blank" rel="noopener" href='https://www.vmware.com/help/privacy/california-privacy-rights.html'>Your California Privacy Rights</a>
|
||||
</span>
|
||||
<span>
|
||||
<a target="_blank" rel="noopener" href="https://github.com/vmware/">
|
||||
<img id="vm-logo" src="/img/vm-logo.svg" alt="VMware logo" />
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</footer>
|
||||
|
||||
@@ -9,13 +9,6 @@
|
||||
<p class="position">Community Manager</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bio">
|
||||
<div class="image"><img src="/img/Anjali-Telang.png" /></div>
|
||||
<div class="info">
|
||||
<p class="name">Anjali Telang</p>
|
||||
<p class="position">Product Manager</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bio">
|
||||
<div class="image"><img src="/img/ryan-richard.png" /></div>
|
||||
<div class="info">
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 28 KiB |
26
site/themes/pinniped/static/img/vm-logo.svg
Normal file
26
site/themes/pinniped/static/img/vm-logo.svg
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="145px" height="23px" viewBox="0 0 145 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>logo</title>
|
||||
<defs>
|
||||
<polygon id="path-1" points="0 0.200376 54.7531875 0.200376 54.7531875 22.999816 0 22.999816"></polygon>
|
||||
</defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Homepage-Rd2" transform="translate(-131.000000, -48.000000)">
|
||||
<g id="logo" transform="translate(131.000000, 48.000000)">
|
||||
<path d="M61.6251356,21.5522986 L55.2042477,3.40907516 C55.1213472,3.15630674 55,2.82609178 55,2.53551481 C55,1.74885313 55.6553949,1 56.592832,1 C57.4113247,1 57.9447717,1.54304048 58.1892683,2.32909235 L63.5084199,17.9607917 L68.8636152,2.28488074 C69.1081118,1.54304048 69.6001085,1 70.4152973,1 L70.5792962,1 C71.4398399,1 71.9723859,1.54304048 72.216582,2.28488074 L77.5309278,17.9607917 L82.9347822,2.24493784 C83.1405317,1.58054412 83.5877742,1 84.4462154,1 C85.3434036,1 86,1.70525134 86,2.49374246 C86,2.78340471 85.8777517,3.11575402 85.7972541,3.36821754 L79.3355166,21.5522986 C79.0039144,22.5039153 78.3509224,23 77.6180335,23 L77.4924812,23 C76.6754903,23 76.0609449,22.5039153 75.7713937,21.5522986 L70.5006007,6.13433953 L65.1823502,21.5522986 C64.8979052,22.5039153 64.281858,23 63.4648671,23 L63.3810654,23 C62.6043233,23 61.9531335,22.5039153 61.6251356,21.5522986" id="Fill-1" fill="#717074"></path>
|
||||
<path d="M109,2.62141195 C109,1.74487421 109.694421,1 110.552765,1 C111.456442,1 112.150863,1.7031198 112.150863,2.62141195 L112.150863,6.30189516 C113.70723,2.72595035 117.154716,1.03809709 119.44003,1.03809709 C120.382137,1.03809709 121,1.74487421 121,2.65676604 C121,3.53269423 120.424168,4.15352433 119.603953,4.28000665 C115.507681,4.77953563 112.150863,7.8958772 112.150863,14.0929015 L112.150863,21.3810263 C112.150863,22.2542115 111.495171,23 110.594796,23 C109.694421,23 109,22.291699 109,21.3810263 L109,2.62141195" id="Fill-3" fill="#717074"></path>
|
||||
<path d="M136.845463,10.815705 C136.517619,6.98696738 134.300304,3.6474607 130.083724,3.6474607 C126.394639,3.6474607 123.603521,6.7011551 123.200846,10.815705 L136.845463,10.815705 Z M130.575643,23 C124.751127,23 120,18.5591955 120,12.0407441 L120,11.9565396 C120,5.89170576 124.30245,1 130.165609,1 C136.432054,1 140,6.08969188 140,11.6743491 C140,12.5293714 139.297697,13.1396274 138.52455,13.1396274 L123.200846,13.1396274 C123.646456,17.7014569 126.883185,20.2671276 130.657528,20.2671276 C133.280891,20.2671276 135.202564,19.2500343 136.763272,17.8221802 C137.005858,17.6223832 137.294753,17.459105 137.665225,17.459105 C138.438679,17.459105 139.059098,18.0714736 139.059098,18.8081872 C139.059098,19.1730732 138.898396,19.5376574 138.563499,19.8216588 C136.556874,21.735424 134.179471,23 130.575643,23 L130.575643,23 Z" id="Fill-5" fill="#717074"></path>
|
||||
<path d="M101.10556,14.7320044 L101.10556,12.6777839 C99.597395,12.2256255 97.5704705,11.7689304 95.0761081,11.7689304 C91.2362947,11.7689304 89.0909798,13.5004399 89.0909798,16.1719549 L89.0909798,16.2539181 C89.0909798,18.9242233 91.4701594,20.4881771 94.2459176,20.4881771 C98.0113725,20.4881771 101.10556,18.1015672 101.10556,14.7320044 M86,16.3788287 L86,16.294446 C86,11.8127853 89.565416,9.42526808 94.7608865,9.42526808 C97.37743,9.42526808 99.2381415,9.79697553 101.068235,10.3310971 L101.068235,9.59010173 C101.068235,5.76565851 98.8010303,3.79128403 94.9609253,3.79128403 C92.8969673,3.79128403 91.6970257,4.06711575 90.1888608,4.76123178 C89.9891135,4.84289249 89.7890747,4.88614243 89.6365669,4.88614243 C88.9215591,4.88614243 88.2841174,4.26642838 88.2841174,3.52906241 C88.2841174,2.87184493 88.562014,2.46596096 89.1213064,2.21009073 C91.1380249,1.30244707 92.6596034,1 95.276147,1 C98.1705871,1 100.39026,1.77698653 101.895218,3.34215012 C103.284701,4.78149574 104,6.83692604 104,9.54987627 L104,21.2860324 C104,22.1894418 103.366058,22.8487765 102.528869,22.8487765 C101.658145,22.8487765 101.068235,22.1894418 101.068235,21.3667858 L101.068235,19.337366 C99.6379277,21.2721199 97.2590397,23 93.656007,23 C89.8468118,23 86,20.7376959 86,16.3788287" id="Fill-7" fill="#717074"></path>
|
||||
<g id="Group-11">
|
||||
<mask id="mask-2" fill="white">
|
||||
<use xlink:href="#path-1"></use>
|
||||
</mask>
|
||||
<g id="Clip-10"></g>
|
||||
<path d="M5.73862228,2.013696 C5.04962772,0.465949333 3.34821467,-0.238157333 1.7606875,0.489869333 C0.171366848,1.215136 -0.415100543,3.02140267 0.3031875,4.57466933 L6.97462772,19.4464693 C8.02201902,21.777136 9.12769837,22.999816 11.2024538,22.999816 C13.4179973,22.999816 14.3846821,21.666736 15.4323723,19.4464693 C15.4323723,19.4464693 21.2513125,6.44748267 21.3078071,6.315616 C21.3693832,6.173936 21.5544103,5.75594933 22.1459592,5.75962933 C22.6469375,5.76484267 23.0684049,6.173936 23.0684049,6.72194933 L23.0684049,19.435736 C23.0684049,21.392576 24.1271549,22.999816 26.1663397,22.999816 C28.1998451,22.999816 29.3019375,21.392576 29.3019375,19.435736 L29.3019375,9.035136 C29.3019375,7.03014933 30.7038397,5.72834933 32.6126984,5.72834933 C34.5209592,5.72834933 35.7913397,7.07124267 35.7913397,9.035136 L35.7913397,19.435736 C35.7913397,21.392576 36.8554701,22.999816 38.8877799,22.999816 C40.9236766,22.999816 42.029356,21.392576 42.029356,19.435736 L42.029356,9.035136 C42.029356,7.03014933 43.4267745,5.72834933 45.3374266,5.72834933 C47.2412038,5.72834933 48.5172636,7.07124267 48.5172636,9.035136 L48.5172636,19.435736 C48.5172636,21.392576 49.5775082,22.999816 51.6143016,22.999816 C53.6484049,22.999816 54.7531875,21.392576 54.7531875,19.435736 L54.7531875,7.59962933 C54.7531875,3.24864267 51.3467745,0.200376 47.2412038,0.200376 C43.1446005,0.200376 40.5778342,3.11156267 40.5778342,3.11156267 C39.2141929,1.29640267 37.3331332,0.203136 34.1509049,0.203136 C30.7929158,0.203136 27.8557962,3.11156267 27.8557962,3.11156267 C26.4885679,1.29640267 24.1669103,0.203136 22.2416114,0.203136 C19.2668288,0.203136 16.9036223,1.54510933 15.4625625,4.929176 L11.2024538,15.2298027 L5.73862228,2.013696" id="Fill-9" fill="#717074" mask="url(#mask-2)"></path>
|
||||
</g>
|
||||
<path d="M144.518938,3.49614043 L144.518938,3.49128023 C144.518938,2.3748642 143.653946,1.46000343 142.498419,1.46000343 C141.352664,1.46000343 140.474453,2.38887301 140.474453,3.49614043 L140.474453,3.51100692 C140.474453,4.62599348 141.342606,5.53713763 142.498419,5.53713763 C143.640439,5.53713763 144.518938,4.60769627 144.518938,3.49614043 M140,3.51357996 L140,3.49614043 C140,2.14043113 141.105523,1 142.498419,1 C143.907696,1 145,2.12956716 145,3.48441878 L145,3.49614043 C145,4.85756761 143.897638,6 142.498419,6 C141.085695,6 140,4.87529304 140,3.51357996" id="Fill-12" fill="#717074"></path>
|
||||
<path d="M142.061016,2.96165608 C142.319016,2.96165608 142.460959,2.85297577 142.460959,2.68219243 L142.460959,2.67607622 C142.460959,2.49282522 142.30906,2.39355446 142.054473,2.39355446 L141.528801,2.39355446 L141.528801,2.96165608 L142.061016,2.96165608 Z M141,2.2208892 C141,2.09762409 141.115489,2 141.264258,2 L142.090883,2 C142.401508,2 142.639596,2.07386497 142.78865,2.20442249 C142.92718,2.3131028 143,2.47165373 143,2.65396377 L143,2.66031522 C143,2.97459421 142.808278,3.16466714 142.520694,3.26440837 L142.88764,3.63232181 C142.937136,3.6868972 142.970132,3.73182781 142.970132,3.79840038 C142.970132,3.91790167 142.848101,4 142.718959,4 C142.603186,4 142.523823,3.94871795 142.460959,3.88920254 L141.948656,3.35121148 L141.528801,3.35121148 L141.528801,3.78193366 C141.528801,3.90355211 141.413312,4 141.264258,4 C141.115489,4 141,3.90355211 141,3.78193366 L141,2.2208892 Z" id="Fill-14" fill="#717074"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
@@ -151,7 +151,7 @@ func TestFailedCredentialRequestWhenTheRequestIsValidButTheTokenDoesNotAuthentic
|
||||
|
||||
require.Empty(t, response.Spec)
|
||||
require.Nil(t, response.Status.Credential)
|
||||
require.Equal(t, pointer.StringPtr("authentication failed"), response.Status.Message)
|
||||
require.Equal(t, pointer.String("authentication failed"), response.Status.Message)
|
||||
}
|
||||
|
||||
// TCRs are non-mutating and safe to run in parallel with serial tests, see main_test.go.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020-2021 the Pinniped contributors. All Rights Reserved.
|
||||
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package integration
|
||||
@@ -132,7 +132,7 @@ func TestLegacyPodCleaner_Parallel(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute)
|
||||
defer cancel()
|
||||
err := kubeClient.CoreV1().Pods(pod.Namespace).Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: pointer.Int64Ptr(0)})
|
||||
err := kubeClient.CoreV1().Pods(pod.Namespace).Delete(ctx, pod.Name, metav1.DeleteOptions{GracePeriodSeconds: pointer.Int64(0)})
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
require.NoError(t, err, "failed to clean up fake legacy agent pod")
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hash"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
@@ -185,11 +187,39 @@ func formpostTemplateServer(t *testing.T, redirectURI string, responseParams url
|
||||
return server.URL
|
||||
}
|
||||
|
||||
type testHMACStrategyConfigurator struct {
|
||||
secret []byte
|
||||
entropy int
|
||||
}
|
||||
|
||||
func newTestHMACStrategyConfigurator(secret []byte, entropy int) hmac.HMACStrategyConfigurator {
|
||||
return &testHMACStrategyConfigurator{
|
||||
secret: secret,
|
||||
entropy: entropy,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *testHMACStrategyConfigurator) GetTokenEntropy(_ context.Context) int {
|
||||
return t.entropy
|
||||
}
|
||||
|
||||
func (t *testHMACStrategyConfigurator) GetGlobalSecret(_ context.Context) ([]byte, error) {
|
||||
return t.secret, nil
|
||||
}
|
||||
|
||||
func (t *testHMACStrategyConfigurator) GetRotatedGlobalSecrets(_ context.Context) ([][]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (t *testHMACStrategyConfigurator) GetHMACHasher(_ context.Context) func() hash.Hash {
|
||||
return nil // nil will cause fosite to use a default hasher
|
||||
}
|
||||
|
||||
// formpostRandomParams is a helper to generate random OAuth2 response parameters for testing.
|
||||
func formpostRandomParams(t *testing.T) url.Values {
|
||||
t.Helper()
|
||||
generator := &hmac.HMACStrategy{GlobalSecret: testlib.RandBytes(t, 32), TokenEntropy: 32}
|
||||
authCode, _, err := generator.Generate()
|
||||
generator := &hmac.HMACStrategy{Config: newTestHMACStrategyConfigurator(testlib.RandBytes(t, 32), 32)}
|
||||
authCode, _, err := generator.Generate(context.Background())
|
||||
require.NoError(t, err)
|
||||
return url.Values{
|
||||
"code": []string{authCode},
|
||||
|
||||
@@ -35,8 +35,8 @@ func TestLDAPSearch_Parallel(t *testing.T) {
|
||||
|
||||
// Note that these tests depend on the values hard-coded in the LDIF file in test/deploy/tools/ldap.yaml.
|
||||
// It requires the test LDAP server from the tools deployment.
|
||||
if len(env.ToolsNamespace) == 0 {
|
||||
t.Skip("Skipping test because it requires the test LDAP server in the tools namespace.")
|
||||
if len(env.ToolsNamespace) == 0 || !strings.Contains(env.SupervisorUpstreamLDAP.Host, "tools.svc.cluster.local") {
|
||||
t.Skip("Skipping test because it requires the test OpenLDAP server in the tools namespace of the target cluster.")
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
@@ -681,8 +681,8 @@ func TestSimultaneousLDAPRequestsOnSingleProvider(t *testing.T) {
|
||||
|
||||
// Note that these tests depend on the values hard-coded in the LDIF file in test/deploy/tools/ldap.yaml.
|
||||
// It requires the test LDAP server from the tools deployment.
|
||||
if len(env.ToolsNamespace) == 0 {
|
||||
t.Skip("Skipping test because it requires the test LDAP server in the tools namespace.")
|
||||
if len(env.ToolsNamespace) == 0 || !strings.Contains(env.SupervisorUpstreamLDAP.Host, "tools.svc.cluster.local") {
|
||||
t.Skip("Skipping test because it requires the test OpenLDAP server in the tools namespace of the target cluster.")
|
||||
}
|
||||
|
||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||
|
||||
@@ -5,6 +5,7 @@ package integration
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
@@ -305,9 +306,11 @@ func TestSupervisorLogin_Browser(t *testing.T) {
|
||||
createIDP: func(t *testing.T) string {
|
||||
var additionalScopes []string
|
||||
// keep all the scopes except for offline access so we can test the access token based refresh flow.
|
||||
if len(env.ToolsNamespace) == 0 {
|
||||
if len(env.ToolsNamespace) == 0 || !strings.Contains(env.SupervisorUpstreamLDAP.Host, "tools.svc.cluster.local") {
|
||||
// Not using Dex.
|
||||
additionalScopes = env.SupervisorUpstreamOIDC.AdditionalScopes
|
||||
} else {
|
||||
// Using Dex in the tools namespace.
|
||||
for _, additionalScope := range env.SupervisorUpstreamOIDC.AdditionalScopes {
|
||||
if additionalScope != "offline_access" {
|
||||
additionalScopes = append(additionalScopes, additionalScope)
|
||||
@@ -2003,7 +2006,7 @@ func testSupervisorLogin(
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedIDTokenClaims := []string{"iss", "exp", "sub", "aud", "auth_time", "iat", "jti", "nonce", "rat", "azp"}
|
||||
expectedIDTokenClaims := []string{"iss", "exp", "sub", "aud", "auth_time", "iat", "jti", "nonce", "rat", "azp", "at_hash"}
|
||||
if slices.Contains(wantDownstreamScopes, "username") {
|
||||
// If the test wants the username scope to have been granted, then also expect the claim in the ID token.
|
||||
expectedIDTokenClaims = append(expectedIDTokenClaims, "username")
|
||||
@@ -2050,7 +2053,7 @@ func testSupervisorLogin(
|
||||
refreshedTokenResponse, err := refreshSource.Token()
|
||||
require.NoError(t, err)
|
||||
|
||||
// When refreshing, expect to get an "at_hash" claim, but no "nonce" claim.
|
||||
// When refreshing, do not expect a "nonce" claim.
|
||||
expectRefreshedIDTokenClaims := []string{"iss", "exp", "sub", "aud", "auth_time", "iat", "jti", "rat", "azp", "at_hash"}
|
||||
if slices.Contains(wantDownstreamScopes, "username") {
|
||||
// If the test wants the username scope to have been granted, then also expect the claim in the refreshed ID token.
|
||||
@@ -2180,6 +2183,21 @@ func verifyTokenResponse(
|
||||
require.NotEmpty(t, tokenResponse.RefreshToken)
|
||||
// Refresh tokens should start with the custom prefix "pin_rt_" to make them identifiable as refresh tokens when seen by a user out of context.
|
||||
require.True(t, strings.HasPrefix(tokenResponse.RefreshToken, "pin_rt_"), "token %q did not have expected prefix 'pin_rt_'", tokenResponse.RefreshToken)
|
||||
|
||||
// The at_hash claim should be present and should be equal to the hash of the access token.
|
||||
actualAccessTokenHashClaimValue := idTokenClaims["at_hash"]
|
||||
require.NotEmpty(t, actualAccessTokenHashClaimValue)
|
||||
require.Equal(t, hashAccessToken(tokenResponse.AccessToken), actualAccessTokenHashClaimValue)
|
||||
}
|
||||
|
||||
func hashAccessToken(accessToken string) string {
|
||||
// See https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken.
|
||||
// "Access Token hash value. Its value is the base64url encoding of the left-most half of
|
||||
// the hash of the octets of the ASCII representation of the access_token value, where the
|
||||
// hash algorithm used is the hash algorithm used in the alg Header Parameter of the ID
|
||||
// Token's JOSE Header."
|
||||
b := sha256.Sum256([]byte(accessToken))
|
||||
return base64.RawURLEncoding.EncodeToString(b[:len(b)/2])
|
||||
}
|
||||
|
||||
func requestAuthorizationAndExpectImmediateRedirectToCallback(t *testing.T, _, downstreamAuthorizeURL, downstreamCallbackURL, _, _ string, _ *http.Client) {
|
||||
|
||||
@@ -34,10 +34,10 @@ func TestAuthorizeCodeStorage(t *testing.T) {
|
||||
name = "pinniped-storage-authcode-jssfhaibxdkiaugxufbsso3bixmfo7fzjvuevxbr35c4xdxolqga"
|
||||
)
|
||||
|
||||
hmac := compose.NewOAuth2HMACStrategy(&compose.Config{}, []byte("super-secret-32-byte-for-testing"), nil)
|
||||
hmac := compose.NewOAuth2HMACStrategy(&fosite.Config{GlobalSecret: []byte("super-secret-32-byte-for-testing")})
|
||||
// test data generation via:
|
||||
// code, signature, err := hmac.GenerateAuthorizeCode(ctx, nil)
|
||||
signature := hmac.AuthorizeCodeSignature(code)
|
||||
signature := hmac.AuthorizeCodeSignature(context.Background(), code)
|
||||
|
||||
secrets := client.CoreV1().Secrets(env.SupervisorNamespace)
|
||||
|
||||
@@ -91,7 +91,7 @@ func TestAuthorizeCodeStorage(t *testing.T) {
|
||||
// Note that CreateAuthorizeCodeSession() sets Active to true and also sets the Version before storing the session,
|
||||
// so expect those here.
|
||||
session.Active = true
|
||||
session.Version = "3" // this is the value of the authorizationcode.authorizeCodeStorageVersion constant
|
||||
session.Version = "4" // this is the value of the authorizationcode.authorizeCodeStorageVersion constant
|
||||
expectedSessionStorageJSON, err := json.Marshal(session)
|
||||
require.NoError(t, err)
|
||||
require.JSONEq(t, string(expectedSessionStorageJSON), string(initialSecret.Data["pinniped-storage-data"]))
|
||||
|
||||
Reference in New Issue
Block a user