mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-05 04:56:11 +00:00
log response audit-id for tokencredentialrequests made from CLI
Only logged when PINNIPED_DEBUG=true is used. Co-authored-by: Joshua Casey <joshuatcasey@gmail.com>
This commit is contained in:
committed by
Joshua Casey
parent
26ec7fa346
commit
6bf9b64778
26
cmd/pinniped/cmd/audit_id.go
Normal file
26
cmd/pinniped/cmd/audit_id.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright 2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go.pinniped.dev/internal/httputil/roundtripper"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
func LogAuditIDTransportWrapper(rt http.RoundTripper) http.RoundTripper {
|
||||
return roundtripper.WrapFunc(rt, func(r *http.Request) (*http.Response, error) {
|
||||
response, responseErr := rt.RoundTrip(r)
|
||||
if response != nil && response.Header.Get("audit-ID") != "" {
|
||||
plog.Info("Received auditID for request",
|
||||
// Use the request path from the response's request, in case the
|
||||
// original request was modified by any other roudtrippers in the chain.
|
||||
"path", response.Request.URL.Path,
|
||||
"statusCode", response.StatusCode,
|
||||
"auditID", response.Header.Get("audit-ID"))
|
||||
}
|
||||
return response, responseErr
|
||||
})
|
||||
}
|
||||
@@ -224,6 +224,7 @@ func runOIDCLogin(cmd *cobra.Command, deps oidcLoginCommandDeps, flags oidcLogin
|
||||
conciergeclient.WithBase64CABundle(flags.conciergeCABundle),
|
||||
conciergeclient.WithAuthenticator(flags.conciergeAuthenticatorType, flags.conciergeAuthenticatorName),
|
||||
conciergeclient.WithAPIGroupSuffix(flags.conciergeAPIGroupSuffix),
|
||||
conciergeclient.WithTransportWrapper(LogAuditIDTransportWrapper),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid Concierge parameters: %w", err)
|
||||
|
||||
@@ -274,8 +274,8 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
wantOptionsCount: 4,
|
||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
|
||||
wantLogs: []string{
|
||||
nowStr + ` cmd/login_oidc.go:267 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` cmd/login_oidc.go:287 No concierge configured, skipping token credential exchange`,
|
||||
nowStr + ` cmd/login_oidc.go:268 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` cmd/login_oidc.go:288 No concierge configured, skipping token credential exchange`,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -319,10 +319,10 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
wantOptionsCount: 12,
|
||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{"interactive":false},"status":{"token":"exchanged-token"}}` + "\n",
|
||||
wantLogs: []string{
|
||||
nowStr + ` cmd/login_oidc.go:267 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` cmd/login_oidc.go:277 Exchanging token for cluster credential {"endpoint": "https://127.0.0.1:1234/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
nowStr + ` cmd/login_oidc.go:285 Successfully exchanged token for cluster credential.`,
|
||||
nowStr + ` cmd/login_oidc.go:292 caching cluster credential for future use.`,
|
||||
nowStr + ` cmd/login_oidc.go:268 Performing OIDC login {"issuer": "test-issuer", "client id": "test-client-id"}`,
|
||||
nowStr + ` cmd/login_oidc.go:278 Exchanging token for cluster credential {"endpoint": "https://127.0.0.1:1234/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
nowStr + ` cmd/login_oidc.go:286 Successfully exchanged token for cluster credential.`,
|
||||
nowStr + ` cmd/login_oidc.go:293 caching cluster credential for future use.`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -113,6 +113,7 @@ func runStaticLogin(cmd *cobra.Command, deps staticLoginDeps, flags staticLoginP
|
||||
conciergeclient.WithBase64CABundle(flags.conciergeCABundle),
|
||||
conciergeclient.WithAuthenticator(flags.conciergeAuthenticatorType, flags.conciergeAuthenticatorName),
|
||||
conciergeclient.WithAPIGroupSuffix(flags.conciergeAPIGroupSuffix),
|
||||
conciergeclient.WithTransportWrapper(LogAuditIDTransportWrapper),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid Concierge parameters: %w", err)
|
||||
|
||||
@@ -147,7 +147,7 @@ func TestLoginStaticCommand(t *testing.T) {
|
||||
Error: could not complete Concierge credential exchange: some concierge error
|
||||
`),
|
||||
wantLogs: []string{
|
||||
nowStr + ` cmd/login_static.go:159 exchanging static token for cluster credential {"endpoint": "https://127.0.0.1/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
nowStr + ` cmd/login_static.go:160 exchanging static token for cluster credential {"endpoint": "https://127.0.0.1/", "authenticator type": "webhook", "authenticator name": "test-authenticator"}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -31,25 +31,25 @@ func configWithWrapper(config *restclient.Config, scheme *runtime.Scheme, negoti
|
||||
return config // invalid input config, will fail existing client-go validation
|
||||
}
|
||||
|
||||
// no need for any wrapping when we have no middleware to inject
|
||||
if len(middlewares) == 0 {
|
||||
return config
|
||||
var middlewareWrapper transport.WrapperFunc
|
||||
if len(middlewares) > 0 {
|
||||
info, ok := runtime.SerializerInfoForMediaType(negotiatedSerializer.SupportedMediaTypes(), config.ContentType)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("unknown content type: %s ", config.ContentType)) // static input, programmer error
|
||||
}
|
||||
regSerializer := info.Serializer // should perform no conversion
|
||||
|
||||
resolver := server.NewRequestInfoResolver(server.NewConfig(serializer.CodecFactory{}))
|
||||
|
||||
schemeRestMapperFunc := schemeRestMapper(scheme)
|
||||
|
||||
middlewareWrapper = newWrapper(hostURL, apiPathPrefix, config, resolver, regSerializer, negotiatedSerializer, schemeRestMapperFunc, middlewares)
|
||||
}
|
||||
|
||||
info, ok := runtime.SerializerInfoForMediaType(negotiatedSerializer.SupportedMediaTypes(), config.ContentType)
|
||||
if !ok {
|
||||
panic(fmt.Errorf("unknown content type: %s ", config.ContentType)) // static input, programmer error
|
||||
}
|
||||
regSerializer := info.Serializer // should perform no conversion
|
||||
|
||||
resolver := server.NewRequestInfoResolver(server.NewConfig(serializer.CodecFactory{}))
|
||||
|
||||
schemeRestMapperFunc := schemeRestMapper(scheme)
|
||||
|
||||
f := newWrapper(hostURL, apiPathPrefix, config, resolver, regSerializer, negotiatedSerializer, schemeRestMapperFunc, middlewares)
|
||||
|
||||
cc := restclient.CopyConfig(config)
|
||||
cc.Wrap(f)
|
||||
if middlewareWrapper != nil {
|
||||
cc.Wrap(middlewareWrapper)
|
||||
}
|
||||
if wrapper != nil {
|
||||
cc.Wrap(wrapper)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/client-go/transport"
|
||||
|
||||
authenticationv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/authentication/v1alpha1"
|
||||
loginv1alpha1 "go.pinniped.dev/generated/latest/apis/concierge/login/v1alpha1"
|
||||
@@ -34,10 +35,11 @@ type Option func(*Client) error
|
||||
|
||||
// Client is a configuration for talking to the Pinniped concierge.
|
||||
type Client struct {
|
||||
authenticator *corev1.TypedLocalObjectReference
|
||||
caBundle string
|
||||
endpoint *url.URL
|
||||
apiGroupSuffix string
|
||||
authenticator *corev1.TypedLocalObjectReference
|
||||
caBundle string
|
||||
endpoint *url.URL
|
||||
apiGroupSuffix string
|
||||
transportWrapper transport.WrapperFunc
|
||||
}
|
||||
|
||||
// WithAuthenticator configures the authenticator reference (spec.authenticator) of the TokenCredentialRequests.
|
||||
@@ -116,6 +118,16 @@ func WithAPIGroupSuffix(apiGroupSuffix string) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithTransportWrapper(wrapper transport.WrapperFunc) Option {
|
||||
return func(c *Client) error {
|
||||
if wrapper == nil {
|
||||
return fmt.Errorf("transport wrapper cannot be nil")
|
||||
}
|
||||
c.transportWrapper = wrapper
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// New validates the specified options and returns a newly initialized *Client.
|
||||
func New(opts ...Option) (*Client, error) {
|
||||
c := Client{apiGroupSuffix: groupsuffix.PinnipedDefaultSuffix}
|
||||
@@ -158,6 +170,7 @@ func (c *Client) clientset() (conciergeclientset.Interface, error) {
|
||||
client, err := kubeclient.New(
|
||||
kubeclient.WithConfig(cfg),
|
||||
kubeclient.WithMiddleware(groupsuffix.New(c.apiGroupSuffix)),
|
||||
kubeclient.WithTransportWrapper(c.transportWrapper),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Reference in New Issue
Block a user