Merge pull request #914 from enj/enj/i/bump_0.23.0
Update all deps to latest where possible, bump Kube deps to v0.23.1
This commit is contained in:
commit
adf04d29f7
@ -2850,7 +2850,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
})
|
||||
issuerEndpointPtr = &issuerEndpoint
|
||||
|
||||
testLog := testlogger.New(t)
|
||||
testLog := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
cmd := kubeconfigCommand(kubeconfigDeps{
|
||||
getPathToSelf: func() (string, error) {
|
||||
if tt.getPathToSelfErr != nil {
|
||||
@ -2876,7 +2876,7 @@ func TestGetKubeconfig(t *testing.T) {
|
||||
}
|
||||
return fake, nil
|
||||
},
|
||||
log: testLog,
|
||||
log: testLog.Logger,
|
||||
})
|
||||
require.NotNil(t, cmd)
|
||||
|
||||
|
@ -358,8 +358,8 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
testLogger := testlogger.New(t)
|
||||
klog.SetLogger(testLogger)
|
||||
testLogger := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
klog.SetLogger(testLogger.Logger)
|
||||
var (
|
||||
gotOptions []oidcclient.Option
|
||||
)
|
||||
|
@ -165,8 +165,8 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
testLogger := testlogger.New(t)
|
||||
klog.SetLogger(testLogger)
|
||||
testLogger := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
klog.SetLogger(testLogger.Logger)
|
||||
cmd := staticLoginCommand(staticLoginDeps{
|
||||
lookupEnv: func(s string) (string, bool) {
|
||||
v, ok := tt.env[s]
|
||||
|
@ -7,8 +7,6 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
//nolint: gochecknoglobals
|
||||
@ -19,12 +17,6 @@ var rootCmd = &cobra.Command{
|
||||
SilenceUsage: true, // do not print usage message when commands fail
|
||||
}
|
||||
|
||||
//nolint: gochecknoinits
|
||||
func init() {
|
||||
// We don't want klog flags showing up in our CLI.
|
||||
plog.RemoveKlogGlobalFlags()
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
|
136
go.mod
136
go.mod
@ -17,153 +17,161 @@ go 1.17
|
||||
// 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.
|
||||
replace (
|
||||
go.opentelemetry.io/otel => go.opentelemetry.io/otel v0.20.0
|
||||
go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v0.20.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/MakeNowJust/heredoc/v2 v2.0.1
|
||||
github.com/coreos/go-oidc/v3 v3.0.0
|
||||
github.com/creack/pty v1.1.14
|
||||
github.com/coreos/go-oidc/v3 v3.1.0
|
||||
github.com/creack/pty v1.1.17
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/felixge/httpsnoop v1.0.2
|
||||
github.com/go-ldap/ldap/v3 v3.4.1
|
||||
github.com/go-logr/logr v0.4.0
|
||||
github.com/go-logr/stdr v0.4.0
|
||||
github.com/go-logr/logr v1.2.2
|
||||
github.com/go-logr/stdr v1.2.2
|
||||
github.com/gofrs/flock v0.8.1
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/google/go-cmp v0.5.6
|
||||
github.com/google/gofuzz v1.2.0
|
||||
github.com/google/uuid v1.2.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/securecookie v1.1.1
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
|
||||
github.com/ory/fosite v0.40.2
|
||||
github.com/ory/x v0.0.212
|
||||
github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4
|
||||
github.com/ory/fosite v0.41.0
|
||||
github.com/ory/x v0.0.321
|
||||
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.2.1
|
||||
github.com/spf13/cobra v1.3.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/tdewolff/minify/v2 v2.9.21
|
||||
go.uber.org/atomic v1.7.0
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
|
||||
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602
|
||||
github.com/tdewolff/minify/v2 v2.9.24
|
||||
go.uber.org/atomic v1.9.0
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3
|
||||
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
|
||||
golang.org/x/text v0.3.6
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
|
||||
golang.org/x/text v0.3.7
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
k8s.io/api v0.22.2
|
||||
k8s.io/apiextensions-apiserver v0.22.2
|
||||
k8s.io/apimachinery v0.22.2
|
||||
k8s.io/apiserver v0.22.2
|
||||
k8s.io/client-go v0.22.2
|
||||
k8s.io/component-base v0.22.2
|
||||
k8s.io/gengo v0.0.0-20210203185629-de9496dff47b
|
||||
k8s.io/klog/v2 v2.10.0
|
||||
k8s.io/kube-aggregator v0.22.1
|
||||
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
k8s.io/api v0.23.1
|
||||
k8s.io/apiextensions-apiserver v0.23.1
|
||||
k8s.io/apimachinery v0.23.1
|
||||
k8s.io/apiserver v0.23.1
|
||||
k8s.io/client-go v0.23.1
|
||||
k8s.io/component-base v0.23.1
|
||||
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185
|
||||
k8s.io/klog/v2 v2.30.0
|
||||
k8s.io/kube-aggregator v0.23.1
|
||||
k8s.io/utils v0.0.0-20211208161948-7d6a63dca704
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.81.0 // indirect
|
||||
cloud.google.com/go v0.99.0 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
github.com/Azure/go-autorest/autorest v0.11.18 // indirect
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect
|
||||
github.com/NYTimes/gziphandler v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/purell v1.1.1 // indirect
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible // indirect
|
||||
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.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
|
||||
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
|
||||
github.com/fsnotify/fsnotify v1.4.9 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.5 // indirect
|
||||
github.com/go-openapi/swag v0.19.14 // indirect
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/googleapis/gnostic v0.5.5 // 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/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.5 // indirect
|
||||
github.com/imdario/mergo v0.3.12 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.11 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/magiconair/properties v1.8.5 // indirect
|
||||
github.com/mailru/easyjson v0.7.6 // indirect
|
||||
github.com/mattn/goveralls v0.0.6 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/goveralls v0.0.11 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/moby/spdystream v0.2.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/ory/go-acc v0.2.6 // indirect
|
||||
github.com/ory/go-convenience v0.1.0 // indirect
|
||||
github.com/ory/viper v1.7.5 // indirect
|
||||
github.com/pborman/uuid v1.2.1 // indirect
|
||||
github.com/pelletier/go-toml v1.9.3 // indirect
|
||||
github.com/pelletier/go-toml v1.9.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 // indirect
|
||||
github.com/prometheus/client_golang v1.11.0 // indirect
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.0.1 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
github.com/prometheus/common v0.32.1 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/spf13/afero v1.6.0 // indirect
|
||||
github.com/spf13/cast v1.3.2-0.20200723214538-8d17101741c8 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/subosito/gotenv v1.2.0 // indirect
|
||||
github.com/tdewolff/parse/v2 v2.5.19 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.0 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.0 // indirect
|
||||
github.com/tdewolff/parse/v2 v2.5.26 // indirect
|
||||
go.etcd.io/etcd/api/v3 v3.5.1 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.1 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.5.0 // indirect
|
||||
go.opentelemetry.io/contrib v0.20.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel v1.0.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/export/metric v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v0.20.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.0.1 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.7.0 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/zap v1.17.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
|
||||
go.uber.org/zap v1.19.0 // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||
golang.org/x/tools v0.1.2 // indirect
|
||||
golang.org/x/tools v0.1.8 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
|
||||
google.golang.org/grpc v1.38.0 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
|
||||
google.golang.org/grpc v1.42.0 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/ini.v1 v1.66.2 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.25 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect
|
||||
)
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
auditinternal "k8s.io/apiserver/pkg/apis/audit"
|
||||
"k8s.io/apiserver/pkg/audit"
|
||||
"k8s.io/apiserver/pkg/audit/policy"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
"k8s.io/apiserver/pkg/authentication/request/bearertoken"
|
||||
@ -211,7 +212,7 @@ func newInternal( //nolint:funlen // yeah, it's kind of long.
|
||||
}
|
||||
|
||||
// wire up a fake audit backend at the metadata level so we can preserve the original user during nested impersonation
|
||||
serverConfig.AuditPolicyChecker = policy.FakeChecker(auditinternal.LevelMetadata, nil)
|
||||
serverConfig.AuditPolicyRuleEvaluator = policy.NewFakePolicyRuleEvaluator(auditinternal.LevelMetadata, nil)
|
||||
serverConfig.AuditBackend = &auditfake.Backend{}
|
||||
|
||||
// Probe the API server to figure out if anonymous auth is enabled.
|
||||
@ -511,7 +512,7 @@ func newImpersonationReverseProxyFunc(restConfig *rest.Config) (func(*genericapi
|
||||
return
|
||||
}
|
||||
|
||||
ae := request.AuditEventFrom(r.Context())
|
||||
ae := audit.AuditEventFrom(r.Context())
|
||||
if ae == nil {
|
||||
plog.Warning("aggregated API server logic did not set audit event but it is always supposed to do so",
|
||||
"url", r.URL.String(),
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/util/httpstream"
|
||||
auditinternal "k8s.io/apiserver/pkg/apis/audit"
|
||||
"k8s.io/apiserver/pkg/audit"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||
"k8s.io/apiserver/pkg/authentication/request/bearertoken"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
@ -712,8 +713,8 @@ func TestImpersonator(t *testing.T) {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
|
||||
case "/apis/flowcontrol.apiserver.k8s.io/v1beta1/prioritylevelconfigurations",
|
||||
"/apis/flowcontrol.apiserver.k8s.io/v1beta1/flowschemas":
|
||||
case "/apis/flowcontrol.apiserver.k8s.io/v1beta2/prioritylevelconfigurations",
|
||||
"/apis/flowcontrol.apiserver.k8s.io/v1beta2/flowschemas":
|
||||
// ignore requests related to priority and fairness logic
|
||||
require.Equal(t, http.MethodGet, r.Method)
|
||||
http.NotFound(w, r)
|
||||
@ -1125,7 +1126,7 @@ func TestImpersonatorHTTPHandler(t *testing.T) {
|
||||
Groups: testGroups,
|
||||
Extra: testExtra,
|
||||
}, nil, "")
|
||||
ctx := request.WithAuditEvent(req.Context(), nil)
|
||||
ctx := audit.WithAuditContext(req.Context(), nil)
|
||||
req = req.WithContext(ctx)
|
||||
return req
|
||||
}(),
|
||||
@ -1880,7 +1881,7 @@ func newRequest(t *testing.T, h http.Header, userInfo user.Info, event *auditint
|
||||
if event != nil {
|
||||
ae = event
|
||||
}
|
||||
ctx = request.WithAuditEvent(ctx, ae)
|
||||
ctx = audit.WithAuditContext(ctx, &audit.AuditContext{Event: ae})
|
||||
|
||||
reqInfo := &request.RequestInfo{
|
||||
IsResourceRequest: false,
|
||||
|
@ -35,7 +35,6 @@ import (
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/issuer"
|
||||
"go.pinniped.dev/internal/kubeclient"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/registry/credentialrequest"
|
||||
)
|
||||
|
||||
@ -96,8 +95,6 @@ func addCommandlineFlagsToCommand(cmd *cobra.Command, app *App) {
|
||||
"/etc/podinfo",
|
||||
"path to Downward API volume mount",
|
||||
)
|
||||
|
||||
plog.RemoveKlogGlobalFlags()
|
||||
}
|
||||
|
||||
// Boot the aggregated API server, which will in turn boot the controllers.
|
||||
|
@ -251,13 +251,10 @@ func TestExpirerControllerSync(t *testing.T) {
|
||||
0,
|
||||
)
|
||||
|
||||
opts := &[]metav1.DeleteOptions{}
|
||||
trackDeleteClient := testutil.NewDeleteOptionsRecorder(kubeAPIClient, opts)
|
||||
|
||||
c := NewCertsExpirerController(
|
||||
namespace,
|
||||
certsSecretResourceName,
|
||||
trackDeleteClient,
|
||||
kubeAPIClient,
|
||||
kubeInformers.Core().V1().Secrets(),
|
||||
controllerlib.WithInformer,
|
||||
test.renewBefore,
|
||||
@ -281,7 +278,7 @@ func TestExpirerControllerSync(t *testing.T) {
|
||||
if test.wantDelete {
|
||||
exActions = append(
|
||||
exActions,
|
||||
kubetesting.NewDeleteAction(
|
||||
kubetesting.NewDeleteActionWithOptions(
|
||||
schema.GroupVersionResource{
|
||||
Group: "",
|
||||
Version: "v1",
|
||||
@ -289,18 +286,12 @@ func TestExpirerControllerSync(t *testing.T) {
|
||||
},
|
||||
namespace,
|
||||
name,
|
||||
testutil.NewPreconditions(testUID, testRV),
|
||||
),
|
||||
)
|
||||
}
|
||||
acActions := kubeAPIClient.Actions()
|
||||
require.Equal(t, exActions, acActions)
|
||||
|
||||
if test.wantDelete {
|
||||
require.Len(t, *opts, 1)
|
||||
require.Equal(t, testutil.NewPreconditions(testUID, testRV), (*opts)[0])
|
||||
} else {
|
||||
require.Len(t, *opts, 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -143,11 +143,11 @@ func TestController(t *testing.T) {
|
||||
if tt.initialCache != nil {
|
||||
tt.initialCache(t, cache)
|
||||
}
|
||||
testLog := testlogger.New(t)
|
||||
testLog := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
|
||||
webhooks := informers.Authentication().V1alpha1().WebhookAuthenticators()
|
||||
jwtAuthenticators := informers.Authentication().V1alpha1().JWTAuthenticators()
|
||||
controller := New(cache, webhooks, jwtAuthenticators, testLog)
|
||||
controller := New(cache, webhooks, jwtAuthenticators, testLog.Logger)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
@ -318,13 +318,13 @@ func TestController(t *testing.T) {
|
||||
fakeClient := pinnipedfake.NewSimpleClientset(tt.jwtAuthenticators...)
|
||||
informers := pinnipedinformers.NewSharedInformerFactory(fakeClient, 0)
|
||||
cache := authncache.New()
|
||||
testLog := testlogger.New(t)
|
||||
testLog := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
|
||||
if tt.cache != nil {
|
||||
tt.cache(t, cache, tt.wantClose)
|
||||
}
|
||||
|
||||
controller := New(cache, informers.Authentication().V1alpha1().JWTAuthenticators(), testLog)
|
||||
controller := New(cache, informers.Authentication().V1alpha1().JWTAuthenticators(), testLog.Logger)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
@ -88,9 +88,9 @@ func TestController(t *testing.T) {
|
||||
fakeClient := pinnipedfake.NewSimpleClientset(tt.webhooks...)
|
||||
informers := pinnipedinformers.NewSharedInformerFactory(fakeClient, 0)
|
||||
cache := authncache.New()
|
||||
testLog := testlogger.New(t)
|
||||
testLog := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
|
||||
controller := New(cache, informers.Authentication().V1alpha1().WebhookAuthenticators(), testLog)
|
||||
controller := New(cache, informers.Authentication().V1alpha1().WebhookAuthenticators(), testLog.Logger)
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
@ -31,6 +30,7 @@ import (
|
||||
corev1informers "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/clock"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
pinnipedclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
|
||||
|
@ -29,12 +29,11 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
kubeinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
kubernetesfake "k8s.io/client-go/kubernetes/fake"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
pinnipedfake "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned/fake"
|
||||
@ -95,7 +94,7 @@ func TestImpersonatorConfigControllerOptions(t *testing.T) {
|
||||
nil,
|
||||
caSignerName,
|
||||
nil,
|
||||
testLog,
|
||||
testLog.Logger,
|
||||
)
|
||||
credIssuerInformerFilter = observableWithInformerOption.GetFilterForInformer(credIssuerInformer)
|
||||
servicesInformerFilter = observableWithInformerOption.GetFilterForInformer(servicesInformer)
|
||||
@ -270,8 +269,6 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
|
||||
var subject controllerlib.Controller
|
||||
var kubeAPIClient *kubernetesfake.Clientset
|
||||
var deleteOptions *[]metav1.DeleteOptions
|
||||
var deleteOptionsRecorder kubernetes.Interface
|
||||
var pinnipedAPIClient *pinnipedfake.Clientset
|
||||
var pinnipedInformerClient *pinnipedfake.Clientset
|
||||
var pinnipedInformers pinnipedinformers.SharedInformerFactory
|
||||
@ -550,7 +547,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
subject = NewImpersonatorConfigController(
|
||||
installedInNamespace,
|
||||
credentialIssuerResourceName,
|
||||
deleteOptionsRecorder,
|
||||
kubeAPIClient,
|
||||
pinnipedAPIClient,
|
||||
pinnipedInformers.Config().V1alpha1().CredentialIssuers(),
|
||||
kubeInformers.Core().V1().Services(),
|
||||
@ -562,11 +559,11 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
tlsSecretName,
|
||||
caSecretName,
|
||||
labels,
|
||||
clock.NewFakeClock(frozenNow),
|
||||
clocktesting.NewFakeClock(frozenNow),
|
||||
impersonatorFunc,
|
||||
caSignerName,
|
||||
signingCertProvider,
|
||||
testLog,
|
||||
testLog.Logger,
|
||||
)
|
||||
controllerlib.TestWrap(t, subject, func(syncer controllerlib.Syncer) controllerlib.Syncer {
|
||||
tlsServingCertDynamicCertProvider = syncer.(*impersonatorConfigController).tlsServingCertDynamicCertProvider
|
||||
@ -1032,10 +1029,7 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
r.Equal("secrets", deleteAction.GetResource().Resource)
|
||||
|
||||
// validate that we set delete preconditions correctly
|
||||
r.NotEmpty(*deleteOptions)
|
||||
for _, opt := range *deleteOptions {
|
||||
r.Equal(testutil.NewPreconditions("uid-1234", "rv-5678"), opt)
|
||||
}
|
||||
r.Equal(testutil.NewPreconditions("uid-1234", "rv-5678"), deleteAction.GetDeleteOptions())
|
||||
}
|
||||
|
||||
var requireCASecretWasCreated = func(action coretesting.Action) []byte {
|
||||
@ -1114,8 +1108,6 @@ func TestImpersonatorConfigControllerSync(t *testing.T) {
|
||||
kubeinformers.WithNamespace(installedInNamespace),
|
||||
)
|
||||
kubeAPIClient = kubernetesfake.NewSimpleClientset()
|
||||
deleteOptions = &[]metav1.DeleteOptions{}
|
||||
deleteOptionsRecorder = testutil.NewDeleteOptionsRecorder(kubeAPIClient, deleteOptions)
|
||||
pinnipedAPIClient = pinnipedfake.NewSimpleClientset()
|
||||
frozenNow = time.Date(2021, time.March, 2, 7, 42, 0, 0, time.Local)
|
||||
signingCertProvider = dynamiccert.NewCA(name)
|
||||
|
@ -23,13 +23,13 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/cache"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
appsv1informers "k8s.io/client-go/informers/apps/v1"
|
||||
corev1informers "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/klog/v2/klogr"
|
||||
"k8s.io/utils/clock"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
|
@ -20,11 +20,11 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/cache"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
kubefake "k8s.io/client-go/kubernetes/fake"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/config/v1alpha1"
|
||||
@ -1027,17 +1027,14 @@ func TestAgentController(t *testing.T) {
|
||||
tt.addKubeReactions(kubeClientset)
|
||||
}
|
||||
|
||||
actualDeleteActionOpts := &[]metav1.DeleteOptions{}
|
||||
trackDeleteKubeClient := testutil.NewDeleteOptionsRecorder(kubeClientset, actualDeleteActionOpts)
|
||||
|
||||
kubeInformers := informers.NewSharedInformerFactory(kubeClientset, 0)
|
||||
log := testlogger.New(t)
|
||||
log := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
mockExecutor := mocks.NewMockPodCommandExecutor(ctrl)
|
||||
mockDynamicCert := mocks.NewMockDynamicCertPrivate(ctrl)
|
||||
fakeClock := clock.NewFakeClock(now)
|
||||
fakeClock := clocktesting.NewFakeClock(now)
|
||||
execCache := cache.NewExpiringWithClock(fakeClock)
|
||||
if tt.mocks != nil {
|
||||
tt.mocks(t, mockExecutor.EXPECT(), mockDynamicCert.EXPECT(), execCache)
|
||||
@ -1059,7 +1056,7 @@ func TestAgentController(t *testing.T) {
|
||||
},
|
||||
DiscoveryURLOverride: tt.discoveryURLOverride,
|
||||
},
|
||||
&kubeclient.Client{Kubernetes: trackDeleteKubeClient, PinnipedConcierge: conciergeClientset},
|
||||
&kubeclient.Client{Kubernetes: kubeClientset, PinnipedConcierge: conciergeClientset},
|
||||
kubeInformers.Core().V1().Pods(),
|
||||
kubeInformers.Apps().V1().Deployments(),
|
||||
kubeInformers.Core().V1().Pods(),
|
||||
@ -1069,13 +1066,13 @@ func TestAgentController(t *testing.T) {
|
||||
mockDynamicCert,
|
||||
fakeClock,
|
||||
execCache,
|
||||
log,
|
||||
log.Logger,
|
||||
)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
|
||||
errorMessages := runControllerUntilQuiet(ctx, t, controller, hasDeploymentSynced(trackDeleteKubeClient, kubeInformers), kubeInformers, conciergeInformers)
|
||||
errorMessages := runControllerUntilQuiet(ctx, t, controller, hasDeploymentSynced(kubeClientset, kubeInformers), kubeInformers, conciergeInformers)
|
||||
|
||||
actualErrors := deduplicate(errorMessages)
|
||||
assert.Subsetf(t, actualErrors, tt.wantDistinctErrors, "required error(s) were not found in the actual errors")
|
||||
@ -1088,16 +1085,20 @@ func TestAgentController(t *testing.T) {
|
||||
|
||||
// Assert on all actions that happened to deployments.
|
||||
var actualDeploymentActionVerbs []string
|
||||
var actualDeleteActionOpts []metav1.DeleteOptions
|
||||
for _, a := range kubeClientset.Actions() {
|
||||
if a.GetResource().Resource == "deployments" && a.GetVerb() != "get" { // ignore gets caused by hasDeploymentSynced
|
||||
actualDeploymentActionVerbs = append(actualDeploymentActionVerbs, a.GetVerb())
|
||||
if deleteAction, ok := a.(coretesting.DeleteAction); ok {
|
||||
actualDeleteActionOpts = append(actualDeleteActionOpts, deleteAction.GetDeleteOptions())
|
||||
}
|
||||
}
|
||||
}
|
||||
if tt.wantDeploymentActionVerbs != nil {
|
||||
assert.Equal(t, tt.wantDeploymentActionVerbs, actualDeploymentActionVerbs)
|
||||
}
|
||||
if tt.wantDeploymentDeleteActionOpts != nil {
|
||||
assert.Equal(t, tt.wantDeploymentDeleteActionOpts, *actualDeleteActionOpts)
|
||||
assert.Equal(t, tt.wantDeploymentDeleteActionOpts, actualDeleteActionOpts)
|
||||
}
|
||||
|
||||
// Assert that the agent deployment is in the expected final state.
|
||||
|
@ -58,12 +58,10 @@ func TestLegacyPodCleanerController(t *testing.T) {
|
||||
wantDistinctErrors []string
|
||||
wantDistinctLogs []string
|
||||
wantActions []coretesting.Action
|
||||
wantDeleteOptions []metav1.DeleteOptions
|
||||
}{
|
||||
{
|
||||
name: "no pods",
|
||||
wantActions: []coretesting.Action{},
|
||||
wantDeleteOptions: []metav1.DeleteOptions{},
|
||||
},
|
||||
{
|
||||
name: "mix of pods",
|
||||
@ -78,12 +76,9 @@ func TestLegacyPodCleanerController(t *testing.T) {
|
||||
},
|
||||
wantActions: []coretesting.Action{ // the first delete triggers the informer again, but the second invocation triggers a Not Found
|
||||
coretesting.NewGetAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
coretesting.NewDeleteAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
coretesting.NewDeleteActionWithOptions(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name, testutil.NewPreconditions("3", "4")),
|
||||
coretesting.NewGetAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
},
|
||||
wantDeleteOptions: []metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("3", "4"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fail to delete",
|
||||
@ -102,13 +97,9 @@ func TestLegacyPodCleanerController(t *testing.T) {
|
||||
},
|
||||
wantActions: []coretesting.Action{
|
||||
coretesting.NewGetAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
coretesting.NewDeleteAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
coretesting.NewDeleteActionWithOptions(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name, testutil.NewPreconditions("3", "4")),
|
||||
coretesting.NewGetAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
coretesting.NewDeleteAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
},
|
||||
wantDeleteOptions: []metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("3", "4"),
|
||||
testutil.NewPreconditions("3", "4"),
|
||||
coretesting.NewDeleteActionWithOptions(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name, testutil.NewPreconditions("3", "4")),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -126,10 +117,7 @@ func TestLegacyPodCleanerController(t *testing.T) {
|
||||
wantDistinctErrors: []string{""},
|
||||
wantActions: []coretesting.Action{
|
||||
coretesting.NewGetAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
coretesting.NewDeleteAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
},
|
||||
wantDeleteOptions: []metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("3", "4"),
|
||||
coretesting.NewDeleteActionWithOptions(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name, testutil.NewPreconditions("3", "4")),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -148,7 +136,6 @@ func TestLegacyPodCleanerController(t *testing.T) {
|
||||
wantActions: []coretesting.Action{
|
||||
coretesting.NewGetAction(corev1.Resource("pods").WithVersion("v1"), "concierge", legacyAgentPodWithExtraLabel.Name),
|
||||
},
|
||||
wantDeleteOptions: []metav1.DeleteOptions{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@ -161,19 +148,16 @@ func TestLegacyPodCleanerController(t *testing.T) {
|
||||
tt.addKubeReactions(kubeClientset)
|
||||
}
|
||||
|
||||
opts := &[]metav1.DeleteOptions{}
|
||||
trackDeleteClient := testutil.NewDeleteOptionsRecorder(kubeClientset, opts)
|
||||
|
||||
kubeInformers := informers.NewSharedInformerFactory(kubeClientset, 0)
|
||||
log := testlogger.New(t)
|
||||
log := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
controller := NewLegacyPodCleanerController(
|
||||
AgentConfig{
|
||||
Namespace: "concierge",
|
||||
Labels: map[string]string{"extralabel": "labelvalue"},
|
||||
},
|
||||
&kubeclient.Client{Kubernetes: trackDeleteClient},
|
||||
&kubeclient.Client{Kubernetes: kubeClientset},
|
||||
kubeInformers.Core().V1().Pods(),
|
||||
log,
|
||||
log.Logger,
|
||||
)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
@ -183,7 +167,6 @@ func TestLegacyPodCleanerController(t *testing.T) {
|
||||
assert.Equal(t, tt.wantDistinctErrors, deduplicate(errorMessages), "unexpected errors")
|
||||
assert.Equal(t, tt.wantDistinctLogs, deduplicate(log.Lines()), "unexpected logs")
|
||||
assert.Equal(t, tt.wantActions, kubeClientset.Actions()[2:], "unexpected actions")
|
||||
assert.Equal(t, tt.wantDeleteOptions, *opts, "unexpected delete options")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -11,10 +11,10 @@ import (
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/client-go/util/retry"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/utils/clock"
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
pinnipedclientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned"
|
||||
|
@ -20,8 +20,8 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
pinnipedfake "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned/fake"
|
||||
@ -116,7 +116,7 @@ func TestSync(t *testing.T) {
|
||||
// Set this at the last second to allow for injection of server override.
|
||||
subject = NewFederationDomainWatcherController(
|
||||
providersSetter,
|
||||
clock.NewFakeClock(frozenNow),
|
||||
clocktesting.NewFakeClock(frozenNow),
|
||||
pinnipedAPIClient,
|
||||
federationDomainInformers.Config().V1alpha1().FederationDomains(),
|
||||
controllerlib.WithInformer,
|
||||
|
@ -91,7 +91,7 @@ func TestOIDCUpstreamWatcherControllerFilterSecret(t *testing.T) {
|
||||
nil,
|
||||
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
|
||||
secretInformer,
|
||||
testLog,
|
||||
testLog.Logger,
|
||||
withInformer.WithInformer,
|
||||
)
|
||||
|
||||
@ -1123,7 +1123,7 @@ oidc: issuer did not match the issuer returned by provider, expected "` + testIs
|
||||
pinnipedInformers := pinnipedinformers.NewSharedInformerFactory(fakePinnipedClient, 0)
|
||||
fakeKubeClient := fake.NewSimpleClientset(tt.inputSecrets...)
|
||||
kubeInformers := informers.NewSharedInformerFactory(fakeKubeClient, 0)
|
||||
testLog := testlogger.New(t)
|
||||
testLog := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
cache := provider.NewDynamicUpstreamIDPProvider()
|
||||
cache.SetOIDCIdentityProviders([]provider.UpstreamOIDCIdentityProviderI{
|
||||
&upstreamoidc.ProviderConfig{Name: "initial-entry"},
|
||||
@ -1134,7 +1134,7 @@ oidc: issuer did not match the issuer returned by provider, expected "` + testIs
|
||||
fakePinnipedClient,
|
||||
pinnipedInformers.IDP().V1alpha1().OIDCIdentityProviders(),
|
||||
kubeInformers.Core().V1().Secrets(),
|
||||
testLog,
|
||||
testLog.Logger,
|
||||
controllerlib.WithInformer,
|
||||
)
|
||||
|
||||
|
@ -13,9 +13,10 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
corev1informers "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/utils/clock"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
pinnipedcontroller "go.pinniped.dev/internal/controller"
|
||||
@ -88,7 +89,7 @@ func GarbageCollectorController(
|
||||
|
||||
func (c *garbageCollectorController) Sync(ctx controllerlib.Context) error {
|
||||
// make sure we have a consistent, static meaning for the current time during the sync loop
|
||||
frozenClock := clock.NewFakeClock(c.clock.Now())
|
||||
frozenClock := clocktesting.NewFakeClock(c.clock.Now())
|
||||
|
||||
// The Sync method is triggered upon any change to any Secret, which would make this
|
||||
// controller too chatty, so it rate limits itself to a more reasonable interval.
|
||||
|
@ -18,11 +18,11 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
kubeinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
kubernetesfake "k8s.io/client-go/kubernetes/fake"
|
||||
kubetesting "k8s.io/client-go/testing"
|
||||
"k8s.io/utils/clock"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/controllerlib"
|
||||
"go.pinniped.dev/internal/fositestorage/accesstoken"
|
||||
@ -127,13 +127,11 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
subject controllerlib.Controller
|
||||
kubeInformerClient *kubernetesfake.Clientset
|
||||
kubeClient *kubernetesfake.Clientset
|
||||
deleteOptions *[]metav1.DeleteOptions
|
||||
deleteOptionsRecorder kubernetes.Interface
|
||||
kubeInformers kubeinformers.SharedInformerFactory
|
||||
cancelContext context.Context
|
||||
cancelContextCancelFunc context.CancelFunc
|
||||
syncContext *controllerlib.Context
|
||||
fakeClock *clock.FakeClock
|
||||
fakeClock *clocktesting.FakeClock
|
||||
frozenNow time.Time
|
||||
)
|
||||
|
||||
@ -144,7 +142,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
subject = GarbageCollectorController(
|
||||
idpCache,
|
||||
fakeClock,
|
||||
deleteOptionsRecorder,
|
||||
kubeClient,
|
||||
kubeInformers.Core().V1().Secrets(),
|
||||
controllerlib.WithInformer,
|
||||
)
|
||||
@ -172,11 +170,9 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
|
||||
kubeInformerClient = kubernetesfake.NewSimpleClientset()
|
||||
kubeClient = kubernetesfake.NewSimpleClientset()
|
||||
deleteOptions = &[]metav1.DeleteOptions{}
|
||||
deleteOptionsRecorder = testutil.NewDeleteOptionsRecorder(kubeClient, deleteOptions)
|
||||
kubeInformers = kubeinformers.NewSharedInformerFactory(kubeInformerClient, 0)
|
||||
frozenNow = time.Now().UTC()
|
||||
fakeClock = clock.NewFakeClock(frozenNow)
|
||||
fakeClock = clocktesting.NewFakeClock(frozenNow)
|
||||
|
||||
unrelatedSecret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -252,18 +248,11 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "first expired secret"),
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "second expired secret"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "first expired secret", testutil.NewPreconditions("uid-123", "rv-456")),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "second expired secret", testutil.NewPreconditions("uid-789", "rv-555")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
r.ElementsMatch(
|
||||
[]metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("uid-123", "rv-456"),
|
||||
testutil.NewPreconditions("uid-789", "rv-555"),
|
||||
},
|
||||
*deleteOptions,
|
||||
)
|
||||
list, err := kubeClient.CoreV1().Secrets(installedInNamespace).List(context.Background(), metav1.ListOptions{})
|
||||
r.NoError(err)
|
||||
r.Len(list.Items, 2)
|
||||
@ -384,18 +373,11 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
// Both authcode session secrets are deleted.
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "activeOIDCAuthcodeSession"),
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "inactiveOIDCAuthcodeSession"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "activeOIDCAuthcodeSession", testutil.NewPreconditions("uid-123", "rv-123")),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "inactiveOIDCAuthcodeSession", testutil.NewPreconditions("uid-456", "rv-456")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
r.ElementsMatch(
|
||||
[]metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("uid-123", "rv-123"),
|
||||
testutil.NewPreconditions("uid-456", "rv-456"),
|
||||
},
|
||||
*deleteOptions,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -460,16 +442,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
// The invalid authcode session secrets is still deleted because it is expired.
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "invalidOIDCAuthcodeSession"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "invalidOIDCAuthcodeSession", testutil.NewPreconditions("uid-123", "rv-123")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
r.ElementsMatch(
|
||||
[]metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("uid-123", "rv-123"),
|
||||
},
|
||||
*deleteOptions,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -536,16 +512,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
// The authcode session secrets is still deleted because it is expired.
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "wrongProviderNameOIDCAuthcodeSession"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "wrongProviderNameOIDCAuthcodeSession", testutil.NewPreconditions("uid-123", "rv-123")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
r.ElementsMatch(
|
||||
[]metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("uid-123", "rv-123"),
|
||||
},
|
||||
*deleteOptions,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -612,16 +582,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
// The authcode session secrets is still deleted because it is expired.
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "wrongProviderNameOIDCAuthcodeSession"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "wrongProviderNameOIDCAuthcodeSession", testutil.NewPreconditions("uid-123", "rv-123")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
r.ElementsMatch(
|
||||
[]metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("uid-123", "rv-123"),
|
||||
},
|
||||
*deleteOptions,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -767,16 +731,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
// The authcode session secrets is deleted.
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "activeOIDCAuthcodeSession"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "activeOIDCAuthcodeSession", testutil.NewPreconditions("uid-123", "rv-123")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
r.ElementsMatch(
|
||||
[]metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("uid-123", "rv-123"),
|
||||
},
|
||||
*deleteOptions,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -893,18 +851,11 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
// Both session secrets are deleted.
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "offlineAccessGrantedOIDCAccessTokenSession"),
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "offlineAccessNotGrantedOIDCAccessTokenSession"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "offlineAccessGrantedOIDCAccessTokenSession", testutil.NewPreconditions("uid-123", "rv-123")),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "offlineAccessNotGrantedOIDCAccessTokenSession", testutil.NewPreconditions("uid-456", "rv-456")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
r.ElementsMatch(
|
||||
[]metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("uid-123", "rv-123"),
|
||||
testutil.NewPreconditions("uid-456", "rv-456"),
|
||||
},
|
||||
*deleteOptions,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -976,16 +927,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
// The secret is deleted.
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "oidcRefreshSession"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "oidcRefreshSession", testutil.NewPreconditions("uid-123", "rv-123")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
r.ElementsMatch(
|
||||
[]metav1.DeleteOptions{
|
||||
testutil.NewPreconditions("uid-123", "rv-123"),
|
||||
},
|
||||
*deleteOptions,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@ -996,6 +941,8 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "expired secret",
|
||||
Namespace: installedInNamespace,
|
||||
UID: "uid-747",
|
||||
ResourceVersion: "rv-609",
|
||||
Annotations: map[string]string{
|
||||
"storage.pinniped.dev/garbage-collect-after": frozenNow.Add(20 * time.Second).Format(time.RFC3339),
|
||||
},
|
||||
@ -1033,7 +980,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
// It should have deleted the expired secret.
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "expired secret"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "expired secret", testutil.NewPreconditions("uid-747", "rv-609")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
@ -1061,6 +1008,8 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "expired secret",
|
||||
Namespace: installedInNamespace,
|
||||
UID: "uid-748",
|
||||
ResourceVersion: "rv-608",
|
||||
Annotations: map[string]string{
|
||||
"storage.pinniped.dev/garbage-collect-after": frozenNow.Add(-time.Second).Format(time.RFC3339),
|
||||
},
|
||||
@ -1076,7 +1025,7 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "expired secret"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "expired secret", testutil.NewPreconditions("uid-748", "rv-608")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
@ -1093,6 +1042,8 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "erroring secret",
|
||||
Namespace: installedInNamespace,
|
||||
UID: "uid-111",
|
||||
ResourceVersion: "rv-222",
|
||||
Annotations: map[string]string{
|
||||
"storage.pinniped.dev/garbage-collect-after": frozenNow.Add(-time.Second).Format(time.RFC3339),
|
||||
},
|
||||
@ -1110,6 +1061,8 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "expired secret",
|
||||
Namespace: installedInNamespace,
|
||||
UID: "uid-333",
|
||||
ResourceVersion: "rv-444",
|
||||
Annotations: map[string]string{
|
||||
"storage.pinniped.dev/garbage-collect-after": frozenNow.Add(-time.Second).Format(time.RFC3339),
|
||||
},
|
||||
@ -1125,8 +1078,8 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
|
||||
|
||||
r.ElementsMatch(
|
||||
[]kubetesting.Action{
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "erroring secret"),
|
||||
kubetesting.NewDeleteAction(secretsGVR, installedInNamespace, "expired secret"),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "erroring secret", testutil.NewPreconditions("uid-111", "rv-222")),
|
||||
kubetesting.NewDeleteActionWithOptions(secretsGVR, installedInNamespace, "expired secret", testutil.NewPreconditions("uid-333", "rv-444")),
|
||||
},
|
||||
kubeClient.Actions(),
|
||||
)
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
k8sinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2/klogr"
|
||||
"k8s.io/utils/clock"
|
||||
|
||||
pinnipedclientset "go.pinniped.dev/generated/latest/client/concierge/clientset/versioned"
|
||||
pinnipedinformers "go.pinniped.dev/generated/latest/client/concierge/informers/externalversions"
|
||||
|
@ -18,9 +18,9 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
)
|
||||
|
||||
func TestStorage(t *testing.T) {
|
||||
@ -62,7 +62,7 @@ func TestStorage(t *testing.T) {
|
||||
name string
|
||||
resource string
|
||||
mocks func(*testing.T, mocker)
|
||||
run func(*testing.T, Storage, *clock.FakeClock) error
|
||||
run func(*testing.T, Storage, *clocktesting.FakeClock) error
|
||||
wantActions []coretesting.Action
|
||||
wantSecrets []corev1.Secret
|
||||
wantErr string
|
||||
@ -71,7 +71,7 @@ func TestStorage(t *testing.T) {
|
||||
name: "get non-existent",
|
||||
resource: "authcode",
|
||||
mocks: nil,
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
_, err := storage.Get(ctx, "not-exists", nil)
|
||||
return err
|
||||
},
|
||||
@ -85,7 +85,7 @@ func TestStorage(t *testing.T) {
|
||||
name: "delete non-existent",
|
||||
resource: "tokens",
|
||||
mocks: nil,
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
return storage.Delete(ctx, "not-a-token")
|
||||
},
|
||||
wantActions: []coretesting.Action{
|
||||
@ -98,7 +98,7 @@ func TestStorage(t *testing.T) {
|
||||
name: "delete non-existent by label",
|
||||
resource: "tokens",
|
||||
mocks: nil,
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
return storage.DeleteByLabel(ctx, "additionalLabel", "matching-value")
|
||||
},
|
||||
wantActions: []coretesting.Action{
|
||||
@ -113,7 +113,7 @@ func TestStorage(t *testing.T) {
|
||||
name: "create and get",
|
||||
resource: "access-tokens",
|
||||
mocks: nil,
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode1)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -177,7 +177,7 @@ func TestStorage(t *testing.T) {
|
||||
name: "create multiple, each gets the correct lifetime timestamp",
|
||||
resource: "access-tokens",
|
||||
mocks: nil,
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
data := &testJSON{Data: "create1"}
|
||||
rv1, err := storage.Create(ctx, "sig1", data, nil)
|
||||
require.Empty(t, rv1) // fake client does not set this
|
||||
@ -272,7 +272,7 @@ func TestStorage(t *testing.T) {
|
||||
name: "create and get with additional labels",
|
||||
resource: "access-tokens",
|
||||
mocks: nil,
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode1)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -360,7 +360,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode2)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -429,7 +429,7 @@ func TestStorage(t *testing.T) {
|
||||
return false, nil, nil // we mutated the secret in place but we do not "handle" it
|
||||
})
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -521,7 +521,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode2)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -615,7 +615,7 @@ func TestStorage(t *testing.T) {
|
||||
Type: "storage.pinniped.dev/walruses",
|
||||
}))
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
return storage.DeleteByLabel(ctx, "additionalLabel", "matching-value")
|
||||
},
|
||||
wantActions: []coretesting.Action{
|
||||
@ -696,7 +696,7 @@ func TestStorage(t *testing.T) {
|
||||
return true, nil, fmt.Errorf("some delete error")
|
||||
})
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
return storage.DeleteByLabel(ctx, "additionalLabel", "matching-value")
|
||||
},
|
||||
wantActions: []coretesting.Action{
|
||||
@ -749,7 +749,7 @@ func TestStorage(t *testing.T) {
|
||||
return true, nil, fmt.Errorf("some listing error")
|
||||
})
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
return storage.DeleteByLabel(ctx, "additionalLabel", "matching-value")
|
||||
},
|
||||
wantActions: []coretesting.Action{
|
||||
@ -783,7 +783,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -847,7 +847,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -911,7 +911,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -975,7 +975,7 @@ func TestStorage(t *testing.T) {
|
||||
})
|
||||
require.NoError(t, err)
|
||||
},
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clock.FakeClock) error {
|
||||
run: func(t *testing.T, storage Storage, fakeClock *clocktesting.FakeClock) error {
|
||||
signature := hmac.AuthorizeCodeSignature(authorizationCode3)
|
||||
require.NotEmpty(t, signature)
|
||||
require.NotEmpty(t, validateSecretName(signature, false)) // signature is not valid secret name as-is
|
||||
@ -1025,7 +1025,7 @@ func TestStorage(t *testing.T) {
|
||||
tt.mocks(t, client)
|
||||
}
|
||||
secrets := client.CoreV1().Secrets(namespace)
|
||||
fakeClock := clock.NewFakeClock(fakeNow)
|
||||
fakeClock := clocktesting.NewFakeClock(fakeNow)
|
||||
storage := New(tt.resource, secrets, fakeClock.Now, lifetime)
|
||||
|
||||
err := tt.run(t, storage, fakeClock)
|
||||
|
@ -16,10 +16,10 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
@ -276,7 +276,7 @@ func TestCreateWithoutRequesterID(t *testing.T) {
|
||||
func makeTestSubject() (context.Context, *fake.Clientset, corev1client.SecretInterface, RevocationStorage) {
|
||||
client := fake.NewSimpleClientset()
|
||||
secrets := client.CoreV1().Secrets(namespace)
|
||||
return context.Background(), client, secrets, New(secrets, clock.NewFakeClock(fakeNow).Now, lifetime)
|
||||
return context.Background(), client, secrets, New(secrets, clocktesting.NewFakeClock(fakeNow).Now, lifetime)
|
||||
}
|
||||
|
||||
func TestReadFromSecret(t *testing.T) {
|
||||
|
@ -196,32 +196,38 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
||||
"client": {
|
||||
"id": ":NJ¸Ɣ8(黋馛ÄRɴJa¶z",
|
||||
"client_secret": "UQ==",
|
||||
"rotated_secrets": [
|
||||
"Bno=",
|
||||
"0j8=",
|
||||
"1c4="
|
||||
],
|
||||
"redirect_uris": [
|
||||
"ǖ枭kʍ切厦ȳ箦;¥ʊXĝ奨誷傥祩d",
|
||||
"ʊXĝ",
|
||||
"Ƿ"
|
||||
],
|
||||
"grant_types": [
|
||||
"祩d",
|
||||
"zŇZ",
|
||||
"優蒼ĊɌț訫DŽǽeʀO2ƚ\u0026N"
|
||||
],
|
||||
"grant_types": [
|
||||
"response_types": [
|
||||
"唐W6ɻ橩斚薛ɑƐ"
|
||||
],
|
||||
"response_types": [
|
||||
"scopes": [
|
||||
"w",
|
||||
"ǔŭe[u@阽羂ŷ-Ĵ½輢OÅ濲喾H"
|
||||
],
|
||||
"scopes": [
|
||||
"audience": [
|
||||
"G螩歐湡ƙı唡ɸğƎ\u0026胢輢Ƈĵƚ"
|
||||
],
|
||||
"audience": [
|
||||
"ě"
|
||||
],
|
||||
"public": false,
|
||||
"jwks_uri": "o*泞羅ʘ Ⱦķ瀊垰7ã\")",
|
||||
"jwks_uri": "潌țjA9;焋Ēƕ",
|
||||
"jwks": {
|
||||
"keys": [
|
||||
{
|
||||
"kty": "OKP",
|
||||
"crv": "Ed25519",
|
||||
"x": "nK9xgX_iN7u3u_i8YOO7ZRT_WK028Vd_nhtsUu7Eo6E",
|
||||
"x": "LHMZ29A64WecPQSLotS8hfZ2mae0SR17CtPdnMDP7ZI",
|
||||
"x5u": {
|
||||
"Scheme": "",
|
||||
"Opaque": "",
|
||||
@ -238,7 +244,24 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
||||
{
|
||||
"kty": "OKP",
|
||||
"crv": "Ed25519",
|
||||
"x": "UbbswQgzWhfGCRlwQmMp6fw_HoIoqkIaKT-2XN2fuYU",
|
||||
"x": "1PwKrC4qDe8cabzGTdA0NjuMJhAZAw7Bu7Tj9z2Y4pE",
|
||||
"x5u": {
|
||||
"Scheme": "",
|
||||
"Opaque": "",
|
||||
"User": null,
|
||||
"Host": "",
|
||||
"Path": "",
|
||||
"RawPath": "",
|
||||
"ForceQuery": false,
|
||||
"RawQuery": "",
|
||||
"Fragment": "",
|
||||
"RawFragment": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"kty": "OKP",
|
||||
"crv": "Ed25519",
|
||||
"x": "j4b-Vld5buh_2KIpjjaDRJ8OY7l7d6XAumvDtVTT9BI",
|
||||
"x5u": {
|
||||
"Scheme": "",
|
||||
"Opaque": "",
|
||||
@ -254,104 +277,107 @@ const ExpectedAuthorizeCodeSessionJSONFromFuzzing = `{
|
||||
}
|
||||
]
|
||||
},
|
||||
"token_endpoint_auth_method": "ƿʥǟȒ伉\u003cx¹T鼓c吏",
|
||||
"token_endpoint_auth_method": "趀Ȁ;hYGe天蹗ĽǙ澅j翕q骽",
|
||||
"request_uris": [
|
||||
"Ć捘j]=谅ʑɑɮ$Ól4Ȟ",
|
||||
",Q7钎漡臧n"
|
||||
"Ǐ蛓ȿ,JwwƐ\u003c涵ØƉKĵ",
|
||||
"Ȟú",
|
||||
"Q7钎漡臧n栀,i"
|
||||
],
|
||||
"request_object_signing_alg": "3@¡廜+v,淬Ʋ4Dʧ呩锏緍场",
|
||||
"token_endpoint_auth_signing_alg": "(ưƓǴ罷ǹ~]ea胠"
|
||||
"request_object_signing_alg": "廜+v,淬Ʋ4Dʧ呩锏緍场脋",
|
||||
"token_endpoint_auth_signing_alg": "ưƓǴ罷ǹ~]ea胠Ĺĩv絹b垇I"
|
||||
},
|
||||
"scopes": [
|
||||
"ĩv絹b垇IŕĩǀŻQ'k頂箨J-a稆",
|
||||
"啶#昏Q遐*\\髎bŸ"
|
||||
"ĩǀŻQ'k頂箨J-a",
|
||||
"ɓ啶#昏Q遐*\\髎bŸ1慂U"
|
||||
],
|
||||
"grantedScopes": [
|
||||
"慂UFƼĮǡ鑻Z"
|
||||
"ƼĮǡ鑻Z¥篚h°ʣ£ǖ%\"砬ʍ"
|
||||
],
|
||||
"form": {
|
||||
"褾攚ŝlĆ厦駳骪l拁乖¡J¿Ƈ妔": [
|
||||
"懧¥ɂĵ~Čyʊ恀c\"NJřðȿ/",
|
||||
"裢?霃谥vƘ:ƿ/濔Aʉ\u003c",
|
||||
"ȭ$奍囀Dž悷鵱民撲ʓeŘ嬀j¤"
|
||||
"¡": [
|
||||
"Ła卦牟懧¥ɂĵ",
|
||||
"ɎǛƍdÚ慂+槰蚪i齥篗裢?霃谥vƘ:",
|
||||
"/濔Aʉ\u003cS獾蔀OƭUǦ"
|
||||
],
|
||||
"诞": [
|
||||
"狲N\u003cCq罉ZPſĝEK郊©l",
|
||||
"餚LJ/ɷȑ潠[ĝU噤'pX ",
|
||||
"Y妶ǵ!ȁu狍ɶȳsčɦƦ诱"
|
||||
"民撲ʓeŘ嬀j¤囡莒汗狲N\u003cCq": [
|
||||
"5ȏ樛ȧ.mĔ櫓Ǩ療騃Ǐ}ɟ",
|
||||
"潠[ĝU噤'",
|
||||
"ŁȗɉY妶ǵ!ȁ"
|
||||
],
|
||||
"褰ʎɰ癟VĎĢ婄磫绒u妔隤ʑƍš駎竪": [
|
||||
"鱙翑ȲŻ麤ã桒嘞\\摗Ǘū稖咾鎅ǸÖ"
|
||||
]
|
||||
},
|
||||
"session": {
|
||||
"fosite": {
|
||||
"Claims": {
|
||||
"JTI": "u妔隤ʑƍš駎竪0ɔ闏À1",
|
||||
"Issuer": "麤ã桒嘞\\摗Ǘū稖咾鎅ǸÖ绝TF",
|
||||
"Subject": "巽ēđų蓼tùZ蛆鬣a\"ÙǞ0觢Û±",
|
||||
"JTI": "褗6巽ēđų蓼tùZ蛆鬣a\"ÙǞ0觢",
|
||||
"Issuer": "j¦鲶H股ƲLŋZ-{",
|
||||
"Subject": "ehpƧ蓟",
|
||||
"Audience": [
|
||||
"H股ƲL",
|
||||
"肟v\u0026đehpƧ",
|
||||
"5^驜Ŗ~ů崧軒q腟u尿"
|
||||
"驜Ŗ~ů崧軒q腟u尿宲!"
|
||||
],
|
||||
"Nonce": "ğ",
|
||||
"ExpiresAt": "2016-11-22T21:33:58.460521133Z",
|
||||
"IssuedAt": "1990-07-25T23:42:07.055978334Z",
|
||||
"RequestedAt": "1971-01-30T00:23:36.377684025Z",
|
||||
"AuthTime": "2088-11-09T12:09:14.051840239Z",
|
||||
"AccessTokenHash": "蕖¤'+ʣȍ瓁U4鞀",
|
||||
"AuthenticationContextClassReference": "ʏÑęN\u003c_z",
|
||||
"AuthenticationMethodsReference": "ț髄A",
|
||||
"CodeHash": "4磔_袻vÓG-壧丵礴鋈k蟵pAɂʅ",
|
||||
"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": [
|
||||
"装ƹýĸŴB岺Ð嫹Sx镯荫őł疂ư墫"
|
||||
],
|
||||
"CodeHash": "\u0026鶡",
|
||||
"Extra": {
|
||||
"#\u0026PƢ曰l騌蘙螤\\阏Đ镴Ƥm蔻ǭ\\鿞": 1677215584,
|
||||
"Y\u0026鶡萷ɵ啜s攦Ɩïdnǔ": {
|
||||
",t猟i\u0026\u0026Q@ǤǟǗǪ飘ȱF?Ƈ": {
|
||||
"~劰û橸ɽ銐ƭ?}H": null,
|
||||
"癑勦e骲v0H晦XŘO溪V蔓": {
|
||||
"碼Ǫ": false
|
||||
"rǓ\\BRë_g\"ʎ啴SƇMǃļū": {
|
||||
"4撎胬龯,t猟i\u0026\u0026Q@ǤǟǗ": [
|
||||
1239190737
|
||||
],
|
||||
"飘ȱF?Ƈ畋": {
|
||||
"劰û橸ɽ銐ƭ?}HƟ玈鳚": null,
|
||||
"骲v0H晦XŘO溪V蔓Ȍ+~ē埅Ȝ": {
|
||||
"4Ǟ": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"钻煐ɨəÅDČ{Ȩʦ4撎": [
|
||||
3684968178
|
||||
]
|
||||
}
|
||||
"鑳绪": 2738428764
|
||||
}
|
||||
},
|
||||
"Headers": {
|
||||
"Extra": {
|
||||
"ĊdŘ鸨EJ毕懴řĬń戹": {
|
||||
"诳DT=3骜Ǹ,": {
|
||||
"\u003e": {
|
||||
"ǰ": false
|
||||
},
|
||||
"ɁOƪ穋嶿鳈恱va": null
|
||||
},
|
||||
"豑觳翢砜Fȏl": [
|
||||
927958776
|
||||
]
|
||||
},
|
||||
"埅ȜʁɁ;Bd謺錳4帳Ņ": 388005986
|
||||
"d謺錳4帳ŅǃĊ": 663773398,
|
||||
"Ř鸨EJ": {
|
||||
"Ǽǟ迍阊v\"豑觳翢砜": [
|
||||
995342744
|
||||
],
|
||||
"ȏl鐉诳DT=3骜Ǹ": {
|
||||
"厷ɁOƪ穋嶿鳈恱va|载ǰɱ汶C]ɲ": null,
|
||||
"荤Ý呐ʣ®DžȪǣǎǔ爣縗ɦü": {
|
||||
"H :靥湤庤毩fɤȆʪ融ƆuŤn": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ExpiresAt": {
|
||||
"C]ɲ'=ĸ闒NȢȰ.醋": "1970-07-19T18:03:29.902062193Z",
|
||||
"fɤȆʪ融ƆuŤn": "2064-01-24T20:34:16.593152073Z",
|
||||
"爣縗ɦüHêQ仏1ő": "2102-03-17T06:24:40.256846902Z"
|
||||
"韁臯氃妪婝rȤ\"h丬鎒ơ娻}ɼƟ": "1970-04-27T04:31:30.902468229Z"
|
||||
},
|
||||
"Username": "韁臯氃妪婝rȤ\"h丬鎒ơ娻}ɼƟ",
|
||||
"Subject": "闺髉龳ǽÙ龦O亾EW莛8嘶×"
|
||||
"Username": "髉龳ǽÙ",
|
||||
"Subject": "\u0026¥潝邎Ȗ莅ŝǔ盕戙鵮碡ʯiŬŽ"
|
||||
},
|
||||
"custom": {
|
||||
"providerUID": "鵮碡ʯiŬŽ非Ĝ眧Ĭ葜SŦ餧Ĭ倏4",
|
||||
"providerName": "nŐǛ3",
|
||||
"providerType": "闣ʬ橳(ý綃ʃʚƟ覣k眐4Ĉt",
|
||||
"providerUID": "Ĝ眧Ĭ",
|
||||
"providerName": "ʼn2ƋŢ觛ǂ焺nŐǛ",
|
||||
"providerType": "ɥ闣ʬ橳(ý綃ʃʚƟ覣k眐4",
|
||||
"oidc": {
|
||||
"upstreamRefreshToken": "嵽痊w©Ź榨Q|ôɵt毇妬"
|
||||
"upstreamRefreshToken": "tC嵽痊w"
|
||||
},
|
||||
"ldap": {
|
||||
"userDN": "6鉢緋uƴŤȱʀļÂ?墖\u003cƬb獭潜Ʃ饾",
|
||||
"userDN": "Ź榨Q|ôɵt毇妬\u003e6鉢緋",
|
||||
"extraRefreshAttributes": {
|
||||
"ď逳鞪?3)藵睋邔\u0026Ű惫蜀Ģ¡圔": "墀jMʥ",
|
||||
"齁š%OpKȱ藚ɏ¬Ê蒭堜]ȗ韚ʫ": "鷞aŚB碠k9帴ʘ赱"
|
||||
"ƍ蛊ʚ£:設虝27": "b獭潜Ʃ饾k|鬌R蜚蠣麹概",
|
||||
"藚ɏ¬Ê蒭堜]ȗ韚ʫ": "鷞aŚB碠k9帴ʘ赱"
|
||||
}
|
||||
},
|
||||
"activedirectory": {
|
||||
|
@ -28,10 +28,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
kubetesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/fositestorage"
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
@ -258,7 +258,7 @@ func TestCreateWithWrongRequesterDataTypes(t *testing.T) {
|
||||
func makeTestSubject() (context.Context, *fake.Clientset, corev1client.SecretInterface, oauth2.AuthorizeCodeStorage) {
|
||||
client := fake.NewSimpleClientset()
|
||||
secrets := client.CoreV1().Secrets(namespace)
|
||||
return context.Background(), client, secrets, New(secrets, clock.NewFakeClock(fakeNow).Now, lifetime)
|
||||
return context.Background(), client, secrets, New(secrets, clocktesting.NewFakeClock(fakeNow).Now, lifetime)
|
||||
}
|
||||
|
||||
// TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession asserts that we can correctly round trip our authorize code session.
|
||||
@ -396,7 +396,7 @@ func TestFuzzAndJSONNewValidEmptyAuthorizeCodeSession(t *testing.T) {
|
||||
// while the fuzzer will panic if AuthorizeRequest changes in a way that cannot be fuzzed,
|
||||
// if it adds a new field that can be fuzzed, this check will fail
|
||||
// thus if AuthorizeRequest changes, we will detect it here (though we could possibly miss an omitempty field)
|
||||
require.JSONEq(t, ExpectedAuthorizeCodeSessionJSONFromFuzzing, authorizeCodeSessionJSONFromFuzzing)
|
||||
require.JSONEq(t, ExpectedAuthorizeCodeSessionJSONFromFuzzing, authorizeCodeSessionJSONFromFuzzing, "actual:\n%s", authorizeCodeSessionJSONFromFuzzing)
|
||||
}
|
||||
|
||||
func TestReadFromSecret(t *testing.T) {
|
||||
|
@ -16,10 +16,10 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
@ -100,7 +100,7 @@ func TestOpenIdConnectStorage(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, request, newRequest)
|
||||
|
||||
err = storage.DeleteOpenIDConnectSession(ctx, "fancy-code.fancy-signature")
|
||||
err = storage.DeleteOpenIDConnectSession(ctx, "fancy-code.fancy-signature") //nolint: staticcheck // we know this is deprecated and never called. our GC controller cleans these up.
|
||||
require.NoError(t, err)
|
||||
|
||||
testutil.LogActualJSONFromCreateAction(t, client, 0) // makes it easier to update expected values when needed
|
||||
@ -200,5 +200,5 @@ func TestAuthcodeHasNoDot(t *testing.T) {
|
||||
func makeTestSubject() (context.Context, *fake.Clientset, corev1client.SecretInterface, openid.OpenIDConnectRequestStorage) {
|
||||
client := fake.NewSimpleClientset()
|
||||
secrets := client.CoreV1().Secrets(namespace)
|
||||
return context.Background(), client, secrets, New(secrets, clock.NewFakeClock(fakeNow).Now, lifetime)
|
||||
return context.Background(), client, secrets, New(secrets, clocktesting.NewFakeClock(fakeNow).Now, lifetime)
|
||||
}
|
||||
|
@ -16,10 +16,10 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
@ -199,5 +199,5 @@ func TestCreateWithWrongRequesterDataTypes(t *testing.T) {
|
||||
func makeTestSubject() (context.Context, *fake.Clientset, corev1client.SecretInterface, pkce.PKCERequestStorage) {
|
||||
client := fake.NewSimpleClientset()
|
||||
secrets := client.CoreV1().Secrets(namespace)
|
||||
return context.Background(), client, secrets, New(secrets, clock.NewFakeClock(fakeNow).Now, lifetime)
|
||||
return context.Background(), client, secrets, New(secrets, clocktesting.NewFakeClock(fakeNow).Now, lifetime)
|
||||
}
|
||||
|
@ -16,10 +16,10 @@ import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
coretesting "k8s.io/client-go/testing"
|
||||
clocktesting "k8s.io/utils/clock/testing"
|
||||
|
||||
"go.pinniped.dev/internal/oidc/clientregistry"
|
||||
"go.pinniped.dev/internal/psession"
|
||||
@ -276,7 +276,7 @@ func TestCreateWithoutRequesterID(t *testing.T) {
|
||||
func makeTestSubject() (context.Context, *fake.Clientset, corev1client.SecretInterface, RevocationStorage) {
|
||||
client := fake.NewSimpleClientset()
|
||||
secrets := client.CoreV1().Secrets(namespace)
|
||||
return context.Background(), client, secrets, New(secrets, clock.NewFakeClock(fakeNow).Now, lifetime)
|
||||
return context.Background(), client, secrets, New(secrets, clocktesting.NewFakeClock(fakeNow).Now, lifetime)
|
||||
}
|
||||
|
||||
func TestReadFromSecret(t *testing.T) {
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
coreosoidc "github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/felixge/httpsnoop"
|
||||
"github.com/ory/fosite"
|
||||
"github.com/ory/fosite/handler/openid"
|
||||
"github.com/ory/fosite/token/jwt"
|
||||
@ -89,7 +90,7 @@ func handleAuthRequestForLDAPUpstream(
|
||||
ldapUpstream provider.UpstreamLDAPIdentityProviderI,
|
||||
idpType psession.ProviderType,
|
||||
) error {
|
||||
authorizeRequester, created := newAuthorizeRequest(r, w, oauthHelper)
|
||||
authorizeRequester, created := newAuthorizeRequest(r, w, oauthHelper, true)
|
||||
if !created {
|
||||
return nil
|
||||
}
|
||||
@ -106,7 +107,7 @@ func handleAuthRequestForLDAPUpstream(
|
||||
}
|
||||
if !authenticated {
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHintf("Username/password not accepted by LDAP provider."))
|
||||
fosite.ErrAccessDenied.WithHintf("Username/password not accepted by LDAP provider."), true)
|
||||
}
|
||||
|
||||
subject := downstreamSubjectFromUpstreamLDAP(ldapUpstream, authenticateResponse)
|
||||
@ -143,7 +144,7 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
oauthHelper fosite.OAuth2Provider,
|
||||
oidcUpstream provider.UpstreamOIDCIdentityProviderI,
|
||||
) error {
|
||||
authorizeRequester, created := newAuthorizeRequest(r, w, oauthHelper)
|
||||
authorizeRequester, created := newAuthorizeRequest(r, w, oauthHelper, true)
|
||||
if !created {
|
||||
return nil
|
||||
}
|
||||
@ -157,7 +158,7 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
// Return a user-friendly error for this case which is entirely within our control.
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHint(
|
||||
"Resource owner password credentials grant is not allowed for this upstream provider according to its configuration."))
|
||||
"Resource owner password credentials grant is not allowed for this upstream provider according to its configuration."), true)
|
||||
}
|
||||
|
||||
token, err := oidcUpstream.PasswordCredentialsGrantAndValidateTokens(r.Context(), username, password)
|
||||
@ -170,7 +171,7 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
// 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.)
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithDebug(err.Error())) // WithDebug hides the error from the client
|
||||
fosite.ErrAccessDenied.WithDebug(err.Error()), true) // WithDebug hides the error from the client
|
||||
}
|
||||
|
||||
if token.RefreshToken == nil || token.RefreshToken.Token == "" {
|
||||
@ -180,14 +181,14 @@ func handleAuthRequestForOIDCUpstreamPasswordGrant(
|
||||
"scopes", oidcUpstream.GetScopes())
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHint(
|
||||
"Refresh token not returned by upstream provider during password grant."))
|
||||
"Refresh token not returned by upstream provider during password grant."), true)
|
||||
}
|
||||
|
||||
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.
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHintf("Reason: %s.", err.Error()),
|
||||
fosite.ErrAccessDenied.WithHintf("Reason: %s.", err.Error()), true,
|
||||
)
|
||||
}
|
||||
|
||||
@ -214,7 +215,7 @@ func handleAuthRequestForOIDCUpstreamAuthcodeGrant(
|
||||
upstreamStateEncoder oidc.Encoder,
|
||||
cookieCodec oidc.Codec,
|
||||
) error {
|
||||
authorizeRequester, created := newAuthorizeRequest(r, w, oauthHelper)
|
||||
authorizeRequester, created := newAuthorizeRequest(r, w, oauthHelper, false)
|
||||
if !created {
|
||||
return nil
|
||||
}
|
||||
@ -231,7 +232,7 @@ func handleAuthRequestForOIDCUpstreamAuthcodeGrant(
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester, err)
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester, err, false)
|
||||
}
|
||||
|
||||
csrfValue, nonceValue, pkceValue, err := generateValues(generateCSRF, generateNonce, generatePKCE)
|
||||
@ -274,7 +275,7 @@ func handleAuthRequestForOIDCUpstreamAuthcodeGrant(
|
||||
|
||||
promptParam := r.Form.Get(promptParamName)
|
||||
if promptParam == promptParamNone && oidc.ScopeWasRequested(authorizeRequester, coreosoidc.ScopeOpenID) {
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester, fosite.ErrLoginRequired)
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester, fosite.ErrLoginRequired, false)
|
||||
}
|
||||
|
||||
for key, val := range oidcUpstream.GetAdditionalAuthcodeParams() {
|
||||
@ -295,13 +296,13 @@ func handleAuthRequestForOIDCUpstreamAuthcodeGrant(
|
||||
encodedStateParamValue,
|
||||
authCodeOptions...,
|
||||
),
|
||||
302,
|
||||
http.StatusSeeOther, // match fosite and https://tools.ietf.org/id/draft-ietf-oauth-security-topics-18.html#section-4.11
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeAuthorizeError(w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, authorizeRequester fosite.AuthorizeRequester, err error) error {
|
||||
func writeAuthorizeError(w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, authorizeRequester fosite.AuthorizeRequester, err error, isBrowserless bool) error {
|
||||
if plog.Enabled(plog.LevelTrace) {
|
||||
// When trace level logging is enabled, include the stack trace in the log message.
|
||||
keysAndValues := oidc.FositeErrorForLog(err)
|
||||
@ -314,6 +315,9 @@ func writeAuthorizeError(w http.ResponseWriter, oauthHelper fosite.OAuth2Provide
|
||||
} else {
|
||||
plog.Info("authorize response error", oidc.FositeErrorForLog(err)...)
|
||||
}
|
||||
if isBrowserless {
|
||||
w = rewriteStatusSeeOtherToStatusFoundForBrowserless(w)
|
||||
}
|
||||
// Return an error according to OIDC spec 3.1.2.6 (second paragraph).
|
||||
oauthHelper.WriteAuthorizeError(w, authorizeRequester, err)
|
||||
return nil
|
||||
@ -333,29 +337,53 @@ func makeDownstreamSessionAndReturnAuthcodeRedirect(
|
||||
|
||||
authorizeResponder, err := oauthHelper.NewAuthorizeResponse(r.Context(), authorizeRequester, openIDSession)
|
||||
if err != nil {
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester, err)
|
||||
return writeAuthorizeError(w, oauthHelper, authorizeRequester, err, true)
|
||||
}
|
||||
|
||||
w = rewriteStatusSeeOtherToStatusFoundForBrowserless(w)
|
||||
oauthHelper.WriteAuthorizeResponse(w, authorizeRequester, authorizeResponder)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func rewriteStatusSeeOtherToStatusFoundForBrowserless(w http.ResponseWriter) http.ResponseWriter {
|
||||
// rewrite http.StatusSeeOther to http.StatusFound for backwards compatibility with old pinniped CLIs.
|
||||
// we can drop this in a few releases once we feel enough time has passed for users to update.
|
||||
//
|
||||
// WriteAuthorizeResponse/WriteAuthorizeError calls used to result in http.StatusFound until
|
||||
// https://github.com/ory/fosite/pull/636 changed it to http.StatusSeeOther to address
|
||||
// https://tools.ietf.org/id/draft-ietf-oauth-security-topics-18.html#section-4.11
|
||||
// Safari has the bad behavior in the case of http.StatusFound and not just http.StatusTemporaryRedirect.
|
||||
//
|
||||
// in the browserless flows, the OAuth client is the pinniped CLI and it already has access to the user's
|
||||
// password. Thus there is no security issue with using http.StatusFound vs. http.StatusSeeOther.
|
||||
return httpsnoop.Wrap(w, httpsnoop.Hooks{
|
||||
WriteHeader: func(delegate httpsnoop.WriteHeaderFunc) httpsnoop.WriteHeaderFunc {
|
||||
return func(code int) {
|
||||
if code == http.StatusSeeOther {
|
||||
code = http.StatusFound
|
||||
}
|
||||
delegate(code)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func requireNonEmptyUsernameAndPasswordHeaders(r *http.Request, w http.ResponseWriter, oauthHelper fosite.OAuth2Provider, authorizeRequester fosite.AuthorizeRequester) (string, string, bool) {
|
||||
username := r.Header.Get(supervisoroidc.AuthorizeUsernameHeaderName)
|
||||
password := r.Header.Get(supervisoroidc.AuthorizePasswordHeaderName)
|
||||
if username == "" || password == "" {
|
||||
_ = writeAuthorizeError(w, oauthHelper, authorizeRequester,
|
||||
fosite.ErrAccessDenied.WithHintf("Missing or blank username or password."))
|
||||
fosite.ErrAccessDenied.WithHintf("Missing or blank username or password."), true)
|
||||
return "", "", false
|
||||
}
|
||||
return username, password, true
|
||||
}
|
||||
|
||||
func newAuthorizeRequest(r *http.Request, w http.ResponseWriter, oauthHelper fosite.OAuth2Provider) (fosite.AuthorizeRequester, bool) {
|
||||
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 {
|
||||
_ = writeAuthorizeError(w, oauthHelper, authorizeRequester, err)
|
||||
_ = writeAuthorizeError(w, oauthHelper, authorizeRequester, err, isBrowserless)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
|
@ -533,7 +533,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: htmlContentType,
|
||||
wantCSRFValueInCookieHeader: happyCSRF,
|
||||
wantLocationHeader: expectedRedirectLocationForUpstreamOIDC(expectedUpstreamStateParam(nil, "", ""), nil),
|
||||
@ -615,7 +615,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
csrfCookie: "__Host-pinniped-csrf=" + encodedIncomingCookieCSRFValue + " ",
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: htmlContentType,
|
||||
wantLocationHeader: expectedRedirectLocationForUpstreamOIDC(expectedUpstreamStateParam(nil, incomingCookieCSRFValue, ""), nil),
|
||||
wantUpstreamStateParamInLocationHeader: true,
|
||||
@ -633,7 +633,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: "/some/path",
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
body: encodeQuery(happyGetRequestQueryMap),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "",
|
||||
wantBodyString: "",
|
||||
wantCSRFValueInCookieHeader: happyCSRF,
|
||||
@ -722,7 +722,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"prompt": "login"}),
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
body: encodeQuery(happyGetRequestQueryMap),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: htmlContentType,
|
||||
wantBodyStringWithLocationInHref: true,
|
||||
wantCSRFValueInCookieHeader: happyCSRF,
|
||||
@ -741,7 +741,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"prompt": "login"}),
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
body: encodeQuery(happyGetRequestQueryMap),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: htmlContentType,
|
||||
wantBodyStringWithLocationInHref: true,
|
||||
wantCSRFValueInCookieHeader: happyCSRF,
|
||||
@ -760,7 +760,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"prompt": "none"}),
|
||||
contentType: "application/x-www-form-urlencoded",
|
||||
body: encodeQuery(happyGetRequestQueryMap),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeLoginRequiredErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -776,7 +776,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: happyGetRequestPath,
|
||||
csrfCookie: "__Host-pinniped-csrf=this-value-was-not-signed-by-pinniped",
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: htmlContentType,
|
||||
// Generated a new CSRF cookie and set it in the response.
|
||||
wantCSRFValueInCookieHeader: happyCSRF,
|
||||
@ -796,7 +796,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
path: modifiedHappyGetRequestPath(map[string]string{
|
||||
"redirect_uri": downstreamRedirectURIWithDifferentPort, // not the same port number that is registered for the client
|
||||
}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: htmlContentType,
|
||||
wantCSRFValueInCookieHeader: happyCSRF,
|
||||
wantLocationHeader: expectedRedirectLocationForUpstreamOIDC(expectedUpstreamStateParam(map[string]string{
|
||||
@ -862,7 +862,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"scope": "openid offline_access"}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: htmlContentType,
|
||||
wantCSRFValueInCookieHeader: happyCSRF,
|
||||
wantLocationHeader: expectedRedirectLocationForUpstreamOIDC(expectedUpstreamStateParam(map[string]string{
|
||||
@ -1170,7 +1170,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"response_type": "unsupported"}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeUnsupportedResponseTypeErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -1217,7 +1217,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"scope": "openid profile email tuna"}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidScopeErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -1268,7 +1268,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"response_type": ""}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingResponseTypeErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -1349,7 +1349,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge": ""}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingCodeChallengeErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -1391,7 +1391,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": "this-is-not-a-valid-pkce-alg"}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidCodeChallengeErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -1433,7 +1433,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": "plain"}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingCodeChallengeMethodErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -1475,7 +1475,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"code_challenge_method": ""}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeMissingCodeChallengeMethodErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -1519,7 +1519,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"prompt": "none login"}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositePromptHasNoneAndOtherValueErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -1566,7 +1566,7 @@ 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"}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: htmlContentType,
|
||||
wantCSRFValueInCookieHeader: happyCSRF,
|
||||
wantLocationHeader: expectedRedirectLocationForUpstreamOIDC(expectedUpstreamStateParam(
|
||||
@ -2049,7 +2049,7 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
cookieEncoder: happyCookieEncoder,
|
||||
method: http.MethodGet,
|
||||
path: modifiedHappyGetRequestPath(map[string]string{"state": "short"}),
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantContentType: "application/json; charset=utf-8",
|
||||
wantLocationHeader: urlWithQuery(downstreamRedirectURI, fositeInvalidStateErrorQuery),
|
||||
wantBodyString: "",
|
||||
@ -2308,8 +2308,16 @@ func TestAuthorizationEndpoint(t *testing.T) {
|
||||
case test.wantBodyJSON != "":
|
||||
require.JSONEq(t, test.wantBodyJSON, rsp.Body.String())
|
||||
case test.wantBodyStringWithLocationInHref:
|
||||
switch code := rsp.Code; code {
|
||||
case http.StatusFound:
|
||||
anchorTagWithLocationHref := fmt.Sprintf("<a href=\"%s\">Found</a>.\n\n", html.EscapeString(actualLocation))
|
||||
require.Equal(t, anchorTagWithLocationHref, rsp.Body.String())
|
||||
case http.StatusSeeOther:
|
||||
anchorTagWithLocationHref := fmt.Sprintf("<a href=\"%s\">See Other</a>.\n\n", html.EscapeString(actualLocation))
|
||||
require.Equal(t, anchorTagWithLocationHref, rsp.Body.String())
|
||||
default:
|
||||
t.Errorf("unexpected response code: %v", code)
|
||||
}
|
||||
default:
|
||||
require.Equal(t, test.wantBodyString, rsp.Body.String())
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -204,7 +204,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -229,7 +229,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -256,7 +256,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -284,7 +284,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound, // succeed despite `email_verified=false` because we're not using the email claim for anything
|
||||
wantStatus: http.StatusSeeOther, // succeed despite `email_verified=false` because we're not using the email claim for anything
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -372,7 +372,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -397,7 +397,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -422,7 +422,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -575,7 +575,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
Build(t, happyStateCodec),
|
||||
).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=&state=` + happyDownstreamState,
|
||||
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -601,7 +601,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
Build(t, happyStateCodec),
|
||||
).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: downstreamRedirectURI + `\?code=([^&]+)&scope=openid\+offline_access&state=` + happyDownstreamState,
|
||||
wantDownstreamIDTokenUsername: oidcUpstreamUsername,
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
@ -698,7 +698,7 @@ func TestCallbackEndpoint(t *testing.T) {
|
||||
method: http.MethodGet,
|
||||
path: newRequestPath().WithState(happyState).String(),
|
||||
csrfCookie: happyCSRFCookie,
|
||||
wantStatus: http.StatusFound,
|
||||
wantStatus: http.StatusSeeOther,
|
||||
wantRedirectLocationRegexp: happyDownstreamRedirectLocationRegexp,
|
||||
wantBody: "",
|
||||
wantDownstreamIDTokenSubject: oidcUpstreamIssuer + "?sub=" + oidcUpstreamSubjectQueryEscaped,
|
||||
|
@ -114,7 +114,7 @@ func (k KubeStorage) GetOpenIDConnectSession(ctx context.Context, fullAuthcode s
|
||||
}
|
||||
|
||||
func (k KubeStorage) DeleteOpenIDConnectSession(ctx context.Context, fullAuthcode string) error {
|
||||
return k.oidcStorage.DeleteOpenIDConnectSession(ctx, fullAuthcode)
|
||||
return k.oidcStorage.DeleteOpenIDConnectSession(ctx, fullAuthcode) //nolint: staticcheck // we know this is deprecated and never called. our GC controller cleans these up.
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -121,7 +121,7 @@ func TestManager(t *testing.T) {
|
||||
r.False(fallbackHandlerWasCalled)
|
||||
|
||||
// Minimal check to ensure that the right endpoint was called
|
||||
r.Equal(http.StatusFound, recorder.Code)
|
||||
r.Equal(http.StatusSeeOther, recorder.Code)
|
||||
actualLocation := recorder.Header().Get("Location")
|
||||
r.True(
|
||||
strings.HasPrefix(actualLocation, expectedRedirectLocationPrefix),
|
||||
@ -160,7 +160,7 @@ func TestManager(t *testing.T) {
|
||||
|
||||
// Check just enough of the response to ensure that we wired up the callback endpoint correctly.
|
||||
// The endpoint's own unit tests cover everything else.
|
||||
r.Equal(http.StatusFound, recorder.Code)
|
||||
r.Equal(http.StatusSeeOther, recorder.Code)
|
||||
actualLocation := recorder.Header().Get("Location")
|
||||
r.True(
|
||||
strings.HasPrefix(actualLocation, downstreamRedirectURL),
|
||||
|
@ -2971,7 +2971,7 @@ func requireValidStoredRequest(
|
||||
|
||||
// At this time, we don't use any of these optional (per the OIDC spec) fields.
|
||||
require.Empty(t, claims.AuthenticationContextClassReference)
|
||||
require.Empty(t, claims.AuthenticationMethodsReference)
|
||||
require.Empty(t, claims.AuthenticationMethodsReferences)
|
||||
require.Empty(t, claims.CodeHash)
|
||||
}
|
||||
|
||||
|
@ -5,40 +5,10 @@ package plog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
//nolint: gochecknoglobals
|
||||
var removeKlogGlobalFlagsLock sync.Mutex
|
||||
|
||||
// RemoveKlogGlobalFlags attempts to "remove" flags that get unconditionally added by importing klog.
|
||||
func RemoveKlogGlobalFlags() {
|
||||
// since we mess with global state, we need a lock to synchronize us when called in parallel during tests
|
||||
removeKlogGlobalFlagsLock.Lock()
|
||||
defer removeKlogGlobalFlagsLock.Unlock()
|
||||
|
||||
// if this function starts to panic, it likely means that klog stopped mucking with global flags
|
||||
const globalLogFlushFlag = "log-flush-frequency"
|
||||
if err := pflag.CommandLine.MarkHidden(globalLogFlushFlag); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := pflag.CommandLine.MarkDeprecated(globalLogFlushFlag, "unsupported"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if pflag.CommandLine.Changed(globalLogFlushFlag) {
|
||||
panic("unsupported global klog flag set")
|
||||
}
|
||||
}
|
||||
|
||||
// KRef is (mostly) copied from klog - it is a standard way to represent a metav1.Object in logs
|
||||
// when you only have access to the namespace and name of the object.
|
||||
func KRef(namespace, name string) string {
|
||||
return fmt.Sprintf("%s/%s", namespace, name)
|
||||
}
|
||||
|
||||
// KObj is (mostly) copied from klog - it is a standard way to represent a metav1.Object in logs.
|
||||
func KObj(obj klog.KMetadata) string {
|
||||
return fmt.Sprintf("%s/%s", obj.GetNamespace(), obj.GetName())
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/sclevine/spec"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -71,11 +72,11 @@ func TestCreate(t *testing.T) {
|
||||
r = require.New(t)
|
||||
ctrl = gomock.NewController(t)
|
||||
logger = testutil.NewTranscriptLogger(t)
|
||||
klog.SetLogger(logger) // this is unfortunately a global logger, so can't run these tests in parallel :(
|
||||
klog.SetLogger(logr.New(logger)) // this is unfortunately a global logger, so can't run these tests in parallel :(
|
||||
})
|
||||
|
||||
it.After(func() {
|
||||
klog.SetLogger(nil)
|
||||
klog.ClearLogger()
|
||||
ctrl.Finish()
|
||||
})
|
||||
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
genericapifilters "k8s.io/apiserver/pkg/endpoints/filters"
|
||||
kubeinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@ -29,6 +28,7 @@ import (
|
||||
"k8s.io/component-base/logs"
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/klog/v2/klogr"
|
||||
"k8s.io/utils/clock"
|
||||
|
||||
configv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/config/v1alpha1"
|
||||
pinnipedclientset "go.pinniped.dev/generated/latest/client/supervisor/clientset/versioned"
|
||||
@ -431,7 +431,6 @@ func runSupervisor(podInfo *downward.PodInfo, cfg *supervisor.Config) error {
|
||||
func main() error { // return an error instead of klog.Fatal to allow defer statements to run
|
||||
logs.InitLogs()
|
||||
defer logs.FlushLogs()
|
||||
plog.RemoveKlogGlobalFlags() // move this whenever the below code gets refactored to use cobra
|
||||
|
||||
klog.Infof("Running %s at %#v", rest.DefaultKubernetesUserAgent(), version.Get())
|
||||
klog.Infof("Command-line arguments were: %s %s %s", os.Args[0], os.Args[1], os.Args[2])
|
||||
|
@ -4,87 +4,10 @@
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
appsv1client "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
func NewDeleteOptionsRecorder(client kubernetes.Interface, opts *[]metav1.DeleteOptions) kubernetes.Interface {
|
||||
return &clientWrapper{
|
||||
Interface: client,
|
||||
opts: opts,
|
||||
}
|
||||
}
|
||||
|
||||
type clientWrapper struct {
|
||||
kubernetes.Interface
|
||||
opts *[]metav1.DeleteOptions
|
||||
}
|
||||
|
||||
func (c *clientWrapper) CoreV1() corev1client.CoreV1Interface {
|
||||
return &coreWrapper{CoreV1Interface: c.Interface.CoreV1(), opts: c.opts}
|
||||
}
|
||||
|
||||
func (c *clientWrapper) AppsV1() appsv1client.AppsV1Interface {
|
||||
return &appsWrapper{AppsV1Interface: c.Interface.AppsV1(), opts: c.opts}
|
||||
}
|
||||
|
||||
type coreWrapper struct {
|
||||
corev1client.CoreV1Interface
|
||||
opts *[]metav1.DeleteOptions
|
||||
}
|
||||
|
||||
func (c *coreWrapper) Pods(namespace string) corev1client.PodInterface {
|
||||
return &podsWrapper{PodInterface: c.CoreV1Interface.Pods(namespace), opts: c.opts}
|
||||
}
|
||||
|
||||
func (c *coreWrapper) Secrets(namespace string) corev1client.SecretInterface {
|
||||
return &secretsWrapper{SecretInterface: c.CoreV1Interface.Secrets(namespace), opts: c.opts}
|
||||
}
|
||||
|
||||
type appsWrapper struct {
|
||||
appsv1client.AppsV1Interface
|
||||
opts *[]metav1.DeleteOptions
|
||||
}
|
||||
|
||||
func (c *appsWrapper) Deployments(namespace string) appsv1client.DeploymentInterface {
|
||||
return &deploymentsWrapper{DeploymentInterface: c.AppsV1Interface.Deployments(namespace), opts: c.opts}
|
||||
}
|
||||
|
||||
type podsWrapper struct {
|
||||
corev1client.PodInterface
|
||||
opts *[]metav1.DeleteOptions
|
||||
}
|
||||
|
||||
func (s *podsWrapper) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
|
||||
*s.opts = append(*s.opts, opts)
|
||||
return s.PodInterface.Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
type secretsWrapper struct {
|
||||
corev1client.SecretInterface
|
||||
opts *[]metav1.DeleteOptions
|
||||
}
|
||||
|
||||
func (s *secretsWrapper) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
|
||||
*s.opts = append(*s.opts, opts)
|
||||
return s.SecretInterface.Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
type deploymentsWrapper struct {
|
||||
appsv1client.DeploymentInterface
|
||||
opts *[]metav1.DeleteOptions
|
||||
}
|
||||
|
||||
func (s *deploymentsWrapper) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error {
|
||||
*s.opts = append(*s.opts, opts)
|
||||
return s.DeploymentInterface.Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
func NewPreconditions(uid types.UID, rv string) metav1.DeleteOptions {
|
||||
return metav1.DeleteOptions{
|
||||
Preconditions: &metav1.Preconditions{
|
||||
|
@ -1001,7 +1001,7 @@ func validateAuthcodeStorage(
|
||||
require.Empty(t, actualClaims.CodeHash)
|
||||
require.Empty(t, actualClaims.AccessTokenHash)
|
||||
require.Empty(t, actualClaims.AuthenticationContextClassReference)
|
||||
require.Empty(t, actualClaims.AuthenticationMethodsReference)
|
||||
require.Empty(t, actualClaims.AuthenticationMethodsReferences)
|
||||
|
||||
// Check that the custom Pinniped session data matches.
|
||||
require.Equal(t, wantCustomSessionData, storedSessionFromAuthcode.Custom)
|
||||
|
168
internal/testutil/testlogger/stdr_copied.go
Normal file
168
internal/testutil/testlogger/stdr_copied.go
Normal file
@ -0,0 +1,168 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package testlogger
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"sort"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/go-logr/stdr"
|
||||
)
|
||||
|
||||
// newStdLogger returns a logr.Logger that matches the legacy v0.4.0 stdr.New implementation.
|
||||
// All unnecessary functionality has been stripped out. Avoid using this if possible.
|
||||
func newStdLogger(std stdr.StdLogger) logr.Logger {
|
||||
return logr.New(logger{
|
||||
std: std,
|
||||
prefix: "",
|
||||
values: nil,
|
||||
})
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
std stdr.StdLogger
|
||||
prefix string
|
||||
values []interface{}
|
||||
}
|
||||
|
||||
func (l logger) clone() logger {
|
||||
out := l
|
||||
l.values = copySlice(l.values)
|
||||
return out
|
||||
}
|
||||
|
||||
func copySlice(in []interface{}) []interface{} {
|
||||
out := make([]interface{}, len(in))
|
||||
copy(out, in)
|
||||
return out
|
||||
}
|
||||
|
||||
// Magic string for intermediate frames that we should ignore.
|
||||
const autogeneratedFrameName = "<autogenerated>"
|
||||
|
||||
// Discover how many frames we need to climb to find the caller. This approach
|
||||
// was suggested by Ian Lance Taylor of the Go team, so it *should* be safe
|
||||
// enough (famous last words).
|
||||
func framesToCaller() int {
|
||||
// 1 is the immediate caller. 3 should be too many.
|
||||
for i := 1; i < 3; i++ {
|
||||
_, file, _, _ := runtime.Caller(i + 1) // +1 for this function's frame
|
||||
if file != autogeneratedFrameName {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return 1 // something went wrong, this is safe
|
||||
}
|
||||
|
||||
func flatten(kvList ...interface{}) string {
|
||||
keys := make([]string, 0, len(kvList))
|
||||
vals := make(map[string]interface{}, len(kvList))
|
||||
for i := 0; i < len(kvList); i += 2 {
|
||||
k, ok := kvList[i].(string)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("key is not a string: %s", pretty(kvList[i])))
|
||||
}
|
||||
var v interface{}
|
||||
if i+1 < len(kvList) {
|
||||
v = kvList[i+1]
|
||||
}
|
||||
keys = append(keys, k)
|
||||
vals[k] = v
|
||||
}
|
||||
sort.Strings(keys)
|
||||
buf := bytes.Buffer{}
|
||||
for i, k := range keys {
|
||||
v := vals[k]
|
||||
if i > 0 {
|
||||
buf.WriteRune(' ')
|
||||
}
|
||||
buf.WriteString(pretty(k))
|
||||
buf.WriteString("=")
|
||||
buf.WriteString(pretty(v))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func pretty(value interface{}) string {
|
||||
jb, _ := json.Marshal(value)
|
||||
return string(jb)
|
||||
}
|
||||
|
||||
func (l logger) Info(level int, msg string, kvList ...interface{}) {
|
||||
if l.Enabled(level) {
|
||||
builtin := make([]interface{}, 0, 4)
|
||||
builtin = append(builtin, "level", level, "msg", msg)
|
||||
builtinStr := flatten(builtin...)
|
||||
fixedStr := flatten(l.values...)
|
||||
userStr := flatten(kvList...)
|
||||
l.output(framesToCaller(), fmt.Sprintln(l.prefix, builtinStr, fixedStr, userStr))
|
||||
}
|
||||
}
|
||||
|
||||
func (l logger) Enabled(level int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (l logger) Error(err error, msg string, kvList ...interface{}) {
|
||||
builtin := make([]interface{}, 0, 4)
|
||||
builtin = append(builtin, "msg", msg)
|
||||
builtinStr := flatten(builtin...)
|
||||
var loggableErr interface{}
|
||||
if err != nil {
|
||||
loggableErr = err.Error()
|
||||
}
|
||||
errStr := flatten("error", loggableErr)
|
||||
fixedStr := flatten(l.values...)
|
||||
userStr := flatten(kvList...)
|
||||
l.output(framesToCaller(), fmt.Sprintln(l.prefix, builtinStr, errStr, fixedStr, userStr))
|
||||
}
|
||||
|
||||
func (l logger) output(calldepth int, s string) {
|
||||
depth := calldepth + 2 // offset for this adapter
|
||||
|
||||
// ignore errors - what can we really do about them?
|
||||
if l.std != nil {
|
||||
_ = l.std.Output(depth, s)
|
||||
} else {
|
||||
_ = log.Output(depth, s)
|
||||
}
|
||||
}
|
||||
|
||||
func (l logger) V(level int) logr.LogSink {
|
||||
return l.clone()
|
||||
}
|
||||
|
||||
// WithName returns a new logr.Logger with the specified name appended. stdr
|
||||
// uses '/' characters to separate name elements. Callers should not pass '/'
|
||||
// in the provided name string, but this library does not actually enforce that.
|
||||
func (l logger) WithName(name string) logr.LogSink {
|
||||
new := l.clone()
|
||||
if len(l.prefix) > 0 {
|
||||
new.prefix = l.prefix + "/"
|
||||
}
|
||||
new.prefix += name
|
||||
return new
|
||||
}
|
||||
|
||||
// WithValues returns a new logr.Logger with the specified key-and-values
|
||||
// saved.
|
||||
func (l logger) WithValues(kvList ...interface{}) logr.LogSink {
|
||||
new := l.clone()
|
||||
new.values = append(new.values, kvList...)
|
||||
return new
|
||||
}
|
||||
|
||||
func (l logger) WithCallDepth(depth int) logr.LogSink {
|
||||
return l.clone()
|
||||
}
|
||||
|
||||
var _ logr.LogSink = logger{}
|
||||
var _ logr.CallDepthLogSink = logger{}
|
||||
|
||||
func (l logger) Init(info logr.RuntimeInfo) {}
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2020 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package testlogger implements a logr.Logger suitable for writing test assertions.
|
||||
// Package testlogger wraps logr.Logger to allow for writing test assertions.
|
||||
package testlogger
|
||||
|
||||
import (
|
||||
@ -17,20 +17,27 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Logger implements logr.Logger in a way that captures logs for test assertions.
|
||||
// Logger wraps logr.Logger in a way that captures logs for test assertions.
|
||||
type Logger struct {
|
||||
logr.Logger
|
||||
Logger logr.Logger
|
||||
t *testing.T
|
||||
buffer syncBuffer
|
||||
}
|
||||
|
||||
// New returns a new test Logger.
|
||||
// New returns a new test Logger. Use this for all new tests.
|
||||
func New(t *testing.T) *Logger {
|
||||
res := Logger{t: t}
|
||||
res.Logger = stdr.New(log.New(&res.buffer, "", 0))
|
||||
return &res
|
||||
}
|
||||
|
||||
// Deprecated: NewLegacy returns a new test Logger. Use this for old tests if necessary.
|
||||
func NewLegacy(t *testing.T) *Logger {
|
||||
res := New(t)
|
||||
res.Logger = newStdLogger(log.New(&res.buffer, "", 0))
|
||||
return res
|
||||
}
|
||||
|
||||
// Lines returns the lines written to the test logger.
|
||||
func (l *Logger) Lines() []string {
|
||||
l.t.Helper()
|
||||
|
@ -17,7 +17,7 @@ type TranscriptLogger struct {
|
||||
transcript []TranscriptLogMessage
|
||||
}
|
||||
|
||||
var _ logr.Logger = &TranscriptLogger{}
|
||||
var _ logr.LogSink = &TranscriptLogger{}
|
||||
|
||||
type TranscriptLogMessage struct {
|
||||
Level string
|
||||
@ -36,7 +36,7 @@ func (log *TranscriptLogger) Transcript() []TranscriptLogMessage {
|
||||
return result
|
||||
}
|
||||
|
||||
func (log *TranscriptLogger) Info(msg string, keysAndValues ...interface{}) {
|
||||
func (log *TranscriptLogger) Info(level int, msg string, keysAndValues ...interface{}) {
|
||||
log.lock.Lock()
|
||||
defer log.lock.Unlock()
|
||||
log.transcript = append(log.transcript, TranscriptLogMessage{
|
||||
@ -54,18 +54,20 @@ func (log *TranscriptLogger) Error(_ error, msg string, _ ...interface{}) {
|
||||
})
|
||||
}
|
||||
|
||||
func (*TranscriptLogger) Enabled() bool {
|
||||
func (log *TranscriptLogger) Enabled(level int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (log *TranscriptLogger) V(_ int) logr.Logger {
|
||||
func (log *TranscriptLogger) V(_ int) logr.LogSink {
|
||||
return log
|
||||
}
|
||||
|
||||
func (log *TranscriptLogger) WithName(_ string) logr.Logger {
|
||||
func (log *TranscriptLogger) WithName(_ string) logr.LogSink {
|
||||
return log
|
||||
}
|
||||
|
||||
func (log *TranscriptLogger) WithValues(_ ...interface{}) logr.Logger {
|
||||
func (log *TranscriptLogger) WithValues(_ ...interface{}) logr.LogSink {
|
||||
return log
|
||||
}
|
||||
|
||||
func (log *TranscriptLogger) Init(info logr.RuntimeInfo) {}
|
||||
|
@ -19,8 +19,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/stdr"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -1571,9 +1569,8 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
testLogger := testlogger.New(t)
|
||||
klog.SetLogger(testLogger)
|
||||
stdr.SetVerbosity(debugLogLevel) // set stdr's global log level to debug so the test logger will send output.
|
||||
testLogger := testlogger.NewLegacy(t) //nolint: staticcheck // old test with lots of log statements
|
||||
klog.SetLogger(testLogger.Logger)
|
||||
|
||||
tok, err := Login(tt.issuer, tt.clientID,
|
||||
WithContext(context.Background()),
|
||||
@ -1581,7 +1578,7 @@ func TestLogin(t *testing.T) { // nolint:gocyclo
|
||||
WithScopes([]string{"test-scope"}),
|
||||
WithSkipBrowserOpen(),
|
||||
tt.opt(t),
|
||||
WithLogger(testLogger),
|
||||
WithLogger(testLogger.Logger),
|
||||
)
|
||||
testLogger.Expect(tt.wantLogs)
|
||||
if tt.wantErr != "" {
|
||||
|
Loading…
Reference in New Issue
Block a user