Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 8 additions & 20 deletions lib/kube/proxy/forwarder.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ import (
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/srv"
"github.com/gravitational/teleport/lib/sshca"
"github.com/gravitational/teleport/lib/tlsca"
"github.com/gravitational/teleport/lib/utils"
)

Expand Down Expand Up @@ -548,31 +547,20 @@ func (f *Forwarder) authenticate(req *http.Request) (*authContext, error) {
if err != nil {
return nil, authz.ConvertAuthorizerError(ctx, f.log, err)
}
peers := req.TLS.PeerCertificates
if len(peers) > 1 {
// when turning intermediaries on, don't forget to verify
// https://github.com/kubernetes/kubernetes/pull/34524/files#diff-2b283dde198c92424df5355f39544aa4R59
return nil, trace.AccessDenied("access denied: intermediaries are not supported")
}
if len(peers) == 0 {
return nil, trace.AccessDenied("access denied: only mutual TLS authentication is supported")
}
clientCert := peers[0]
clientIdentity, err := tlsca.FromSubject(clientCert.Subject, clientCert.NotAfter)
if err != nil {
return nil, trace.Wrap(err)
}

// kubeResource is the Kubernetes Resource the request is targeted at.
// Currently only supports Pods and it includes the pod name and namespace.
kubeResource := getPodResourceFromRequest(req.RequestURI)
authContext, err := f.setupContext(ctx, *userContext, req, isRemoteUser, clientIdentity, kubeResource)
authContext, err := f.setupContext(ctx, *userContext, req, isRemoteUser, kubeResource)
if err != nil {
f.log.WithError(err).Warn("Unable to setup context.")
if trace.IsAccessDenied(err) {
if kubeResource != nil {
return nil, trace.AccessDenied(
kubeResourceDeniedAccessMsg(
clientIdentity.Username,
// return the unmapped username to the client, otherwise for leaf
// clusters the client will see the "remote-username".
userContext.UnmappedIdentity.GetIdentity().Username,
req.Method,
kubeResource,
),
Expand Down Expand Up @@ -754,7 +742,7 @@ func (f *Forwarder) formatStatusResponseError(rw http.ResponseWriter, respErr er
}
}

func (f *Forwarder) setupContext(ctx context.Context, authCtx authz.Context, req *http.Request, isRemoteUser bool, clientIdentity *tlsca.Identity, kubeResource *types.KubernetesResource) (*authContext, error) {
func (f *Forwarder) setupContext(ctx context.Context, authCtx authz.Context, req *http.Request, isRemoteUser bool, kubeResource *types.KubernetesResource) (*authContext, error) {
ctx, span := f.cfg.tracer.Start(
ctx,
"kube.Forwarder/setupContext",
Expand Down Expand Up @@ -955,8 +943,8 @@ func (f *Forwarder) setupContext(ctx context.Context, authCtx authz.Context, req
recordingConfig: recordingConfig,
kubeClusterName: kubeCluster,
kubeResource: kubeResource,
certExpires: clientIdentity.Expires,
disconnectExpiredCert: srv.GetDisconnectExpiredCertFromIdentity(roles, authPref, clientIdentity),
certExpires: identity.Expires,
disconnectExpiredCert: srv.GetDisconnectExpiredCertFromIdentity(roles, authPref, &identity),
teleportCluster: teleportClusterClient{
name: teleportClusterName,
remoteAddr: utils.NetAddr{AddrNetwork: "tcp", Addr: req.RemoteAddr},
Expand Down
2 changes: 1 addition & 1 deletion lib/kube/proxy/forwarder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ func TestAuthenticate(t *testing.T) {
RouteToCluster: tt.routeToCluster,
KubernetesCluster: tt.kubernetesCluster,
ActiveRequests: tt.activeRequests,
Expires: certExpiration,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I add this line, but don't add the fixes above, the test still passes.

This makes me think we don't actually have a test that verifies this behavior is correct.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was a nice catch although the test was correct. I didn't remove the expiration from the certificate and it was picking that value.
Fixed by 1cbc54b

}),
}
authorizer := mockAuthorizer{ctx: &authCtx}
Expand All @@ -769,7 +770,6 @@ func TestAuthenticate(t *testing.T) {
CommonName: username,
Organization: []string{"example"},
},
NotAfter: certExpiration,
},
},
},
Expand Down