Skip to content

Commit

Permalink
Always add 'system:authenticated' to impersonation groups.
Browse files Browse the repository at this point in the history
Looks like impersonated users do not get 'system:authenticated'
as a default. This leads to kubectl to fail for some restricted users,
who don't have 'system:discovery' like permissions added to the roles.

This commit always injects the group if not present in the request.

See kubernetes/kubernetes#43227 for a similar
solution
  • Loading branch information
klizhentas committed Mar 25, 2019
1 parent 0c7912f commit c805de5
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 69 deletions.
5 changes: 5 additions & 0 deletions constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,11 @@ const (
// KubeSystemMasters is a name of the builtin kubernets group for master nodes
KubeSystemMasters = "system:masters"

// KubeSystemAuthenticated is a builtin group that allows
// any user to access common API methods, e.g. discovery methods
// required for initial client usage
KubeSystemAuthenticated = "system:authenticated"

// UsageKubeOnly specifies certificate usage metadata
// that limits certificate to be only used for kubernetes proxying
UsageKubeOnly = "usage:kube"
Expand Down
11 changes: 10 additions & 1 deletion lib/kube/proxy/forwarder.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ type authContext struct {
clusterConfig services.ClusterConfig
// clientIdleTimeout sets information on client idle timeout
clientIdleTimeout time.Duration
// disconnectExpiredCert time.Time
// disconnectExpiredCert if set, controls the time when the connection
// should be disconnected because the client cert expires
disconnectExpiredCert time.Time
// sessionTTL specifies the duration of the user's session
sessionTTL time.Duration
Expand Down Expand Up @@ -357,6 +358,14 @@ func (f *Forwarder) setupContext(ctx auth.AuthContext, req *http.Request, isRemo
return nil, trace.Wrap(err)
}

// KubeSystemAuthenticated is a builtin group that allows
// any user to access common API methods, e.g. discovery methods
// required for initial client usage, without it, restricted user's
// kubectl clients will not work
if !utils.SliceContainsStr(kubeGroups, teleport.KubeSystemAuthenticated) {
kubeGroups = append(kubeGroups, teleport.KubeSystemAuthenticated)
}

var isRemoteCluster bool
targetCluster, err := f.Tunnel.GetSite(f.ClusterName)
if err != nil {
Expand Down
65 changes: 0 additions & 65 deletions lib/srv/ctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,71 +359,6 @@ func (c *ServerContext) CreateOrJoinSession(reg *SessionRegistry) error {
return nil
}

func (c *ServerContext) periodicCheckDisconnect() {
var certTime <-chan time.Time
if !c.disconnectExpiredCert.IsZero() {
t := time.NewTimer(c.disconnectExpiredCert.Sub(c.srv.GetClock().Now().UTC()))
defer t.Stop()
certTime = t.C
}

var idleTimer *time.Timer
var idleTime <-chan time.Time
if c.clientIdleTimeout != 0 {
idleTimer = time.NewTimer(c.clientIdleTimeout)
idleTime = idleTimer.C
}

for {
select {
// certificate has expired, disconnect
case <-certTime:
event := events.EventFields{
events.EventType: events.ClientDisconnectEvent,
events.EventLogin: c.Identity.Login,
events.EventUser: c.Identity.TeleportUser,
events.LocalAddr: c.Conn.LocalAddr().String(),
events.RemoteAddr: c.Conn.RemoteAddr().String(),
events.SessionServerID: c.srv.ID(),
events.Reason: fmt.Sprintf("client certificate expired at %v", c.clientLastActive),
}
c.srv.EmitAuditEvent(events.ClientDisconnectEvent, event)
c.Debugf("Disconnecting client: %v", event[events.Reason])
c.Conn.Close()
return
case <-idleTime:
now := c.srv.GetClock().Now()
clientLastActive := c.GetClientLastActive()
c.Debugf("client last active %v, client idle timeout %v", clientLastActive, c.clientIdleTimeout)
if now.Sub(clientLastActive) >= c.clientIdleTimeout {
event := events.EventFields{
events.EventLogin: c.Identity.Login,
events.EventUser: c.Identity.TeleportUser,
events.LocalAddr: c.Conn.LocalAddr().String(),
events.RemoteAddr: c.Conn.RemoteAddr().String(),
events.SessionServerID: c.srv.ID(),
}
if clientLastActive.IsZero() {
event[events.Reason] = "client reported no activity"
} else {
event[events.Reason] = fmt.Sprintf("client is idle for %v, exceeded idle timeout of %v",
now.Sub(clientLastActive), c.clientIdleTimeout)
}
c.Debugf("Disconnecting client: %v", event[events.Reason])
c.srv.EmitAuditEvent(events.ClientDisconnectEvent, event)
c.Conn.Close()
return
}
c.Debugf("Next check in %v", c.clientIdleTimeout-now.Sub(clientLastActive))
idleTimer = time.NewTimer(c.clientIdleTimeout - now.Sub(clientLastActive))
idleTime = idleTimer.C
case <-c.cancelContext.Done():
c.Debugf("Releasing associated resources - context has been closed.")
return
}
}
}

// GetClientLastActive returns time when client was last active
func (c *ServerContext) GetClientLastActive() time.Time {
c.RLock()
Expand Down
7 changes: 4 additions & 3 deletions lib/srv/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ import (
log "github.com/sirupsen/logrus"
)

// ActivityTracker is activity tracker
// ActivityTracker is a connection activity tracker,
// it allows to update the activity on the connection
// and retrieve the time when the connection was last active
type ActivityTracker interface {
// GetClientLastActive returns the time of the last recorded activity
GetClientLastActive() time.Time
// UpdateClient
// UpdateClient updates client activity
UpdateClientActivity()
}

Expand Down Expand Up @@ -155,7 +157,6 @@ func (w *Monitor) Start() {
case <-idleTime:
now := w.Clock.Now().UTC()
clientLastActive := w.Tracker.GetClientLastActive()
w.Entry.Debugf("client last active %v, client idle timeout %v", clientLastActive, w.ClientIdleTimeout)
if now.Sub(clientLastActive) >= w.ClientIdleTimeout {
event := events.EventFields{
events.EventLogin: w.Login,
Expand Down

0 comments on commit c805de5

Please sign in to comment.