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:
Mo Khan 2021-12-16 21:45:32 -05:00 committed by GitHub
commit adf04d29f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 1562 additions and 643 deletions

View File

@ -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)

View File

@ -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
)

View File

@ -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]

View File

@ -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
View File

@ -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
)

1086
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -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(),

View File

@ -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,

View File

@ -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.

View File

@ -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)
}
})
}
}

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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.

View File

@ -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: "no pods",
wantActions: []coretesting.Action{},
},
{
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")
})
}
}

View File

@ -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"

View File

@ -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,

View File

@ -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,
)

View File

@ -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.

View File

@ -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,
)
})
})
@ -994,8 +939,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
// Add a secret that will expire in 20 seconds.
expiredSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "expired secret",
Namespace: installedInNamespace,
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(),
)
@ -1059,8 +1006,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
r.NoError(kubeClient.Tracker().Add(malformedSecret))
expiredSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "expired secret",
Namespace: installedInNamespace,
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(),
)
@ -1091,8 +1040,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
it.Before(func() {
erroringSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "erroring secret",
Namespace: installedInNamespace,
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),
},
@ -1108,8 +1059,10 @@ func TestGarbageCollectorControllerSync(t *testing.T) {
})
expiredSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "expired secret",
Namespace: installedInNamespace,
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(),
)

View File

@ -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"

View File

@ -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)

View File

@ -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) {

View File

@ -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": {

View File

@ -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) {

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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) {

View File

@ -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
}

View File

@ -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:
anchorTagWithLocationHref := fmt.Sprintf("<a href=\"%s\">Found</a>.\n\n", html.EscapeString(actualLocation))
require.Equal(t, anchorTagWithLocationHref, rsp.Body.String())
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())
}

View File

@ -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,

View File

@ -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.
}
//

View File

@ -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),

View File

@ -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)
}

View File

@ -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())

View File

@ -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()
})

View File

@ -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])

View File

@ -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{

View File

@ -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)

View 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) {}

View File

@ -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()

View File

@ -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) {}

View File

@ -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 != "" {