-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Session access controls #1224
Session access controls #1224
Conversation
d97655a
to
7e347af
Compare
lib/auth/apiserver.go
Outdated
@@ -181,6 +181,7 @@ func NewAPIServer(config *APIConfig) http.Handler { | |||
// Audit logs AKA events | |||
srv.POST("/:version/events", srv.withAuth(srv.emitAuditEvent)) | |||
srv.GET("/:version/events", srv.withAuth(srv.searchEvents)) | |||
srv.GET("/:version/events/session", srv.withAuth(srv.searchSessionEvents)) // return session related events |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment is redundant
lib/auth/clt.go
Outdated
@@ -1227,6 +1227,26 @@ func (c *Client) SearchEvents(from, to time.Time, query string) ([]events.EventF | |||
return retval, nil | |||
} | |||
|
|||
// SearchSessionEvents returns session relayed events to find completed sessions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
session-related
@@ -141,6 +141,10 @@ type IAuditLog interface { | |||
// The only mandatory requirement is a date range (UTC). Results must always | |||
// show up sorted by date (newest first) | |||
SearchEvents(fromUTC, toUTC time.Time, query string) ([]EventFields, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not simply extend query to add query type for session type events instead of adding extra method?
lib/reversetunnel/agent.go
Outdated
servers = append(servers, server) | ||
} | ||
|
||
log.Infof("got out of band request %v", servers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debugf
lib/reversetunnel/agent.go
Outdated
break | ||
} | ||
|
||
// log the error if we were not able to connect | ||
log.Error(trace.DebugReport(err)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not an error, connection could fail for various reasons
lib/reversetunnel/agent.go
Outdated
|
||
log.Infof("got out of band request %v", servers) | ||
|
||
var connected bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
connected flag seems redundant, because conn != nil
should do the same
lib/web/apiserver.go
Outdated
return fn(w, r, p, ctx, site) | ||
}) | ||
} | ||
|
||
// clientWithUserRole will return an auth.ClientI with the role of the user at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be a method of SessionContext
lib/web/apiserver.go
Outdated
} | ||
|
||
// remoteClient returns a client to a remote site with the role of logged in user. | ||
func remoteClient(ctx *SessionContext, site reversetunnel.RemoteSite) (auth.ClientI, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
lib/web/apiserver.go
Outdated
// the requested site. If the site is local a client with the users local role | ||
// is returned. If the site is remote a client with the users remote role is | ||
// returned. | ||
func clientWithUserRole(ctx *SessionContext, site reversetunnel.RemoteSite) (auth.ClientI, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clientWithUserRole -> ctx.GetUserClient()
lib/web/apiserver.go
Outdated
return client.Dial(network, addr) | ||
} | ||
|
||
clt, err := auth.NewClient("http://stub:0", sshDialer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you will be creating clients on every request. This client should be associated with active user session and should be deleted when the session closes. Extend the logic of the SessionContext
to support additional use case.
lib/web/apiserver.go
Outdated
// remote cluster from our local cluster | ||
agent, err := ctx.GetAgent() | ||
if err != nil { | ||
return nil, trace.Wrap(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
connection above should be closed if you failed to get agent here, otherwise it will be orphaned resource.
lib/web/apiserver.go
Outdated
} | ||
principal, authMethods, err := getUserCredentials(agent) | ||
if err != nil { | ||
return nil, trace.Wrap(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
lib/web/apiserver.go
Outdated
} | ||
sshConn, sshChans, sshReqs, err := ssh.NewClientConn(netConn, reversetunnel.RemoteAuthServer, config) | ||
if err != nil { | ||
return nil, trace.Wrap(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are several issues to be fixed with this PR especially around resource handling.
6181402
to
c580f7d
Compare
lib/web/sessions.go
Outdated
} | ||
|
||
// look to see if we already have a connection to this cluster | ||
remoteClt, ok := c.remoteClt[site.GetName()] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this could be accessed concurrently, because the session can be used in multiple requests at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should protect the access to the client with read write mutex, I suggest to use separate small function with defer for that.
lib/web/sessions.go
Outdated
// we'll save the remote client in our session context so we don't have to | ||
// build a new connection next time. all remote clients will be closed when | ||
// the session context is closed. | ||
c.remoteClt[site.GetName()] = rClt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should call AddCloser
here to close client if it supports closing
lib/web/sessions.go
Outdated
return nil, trace.Wrap(err) | ||
} | ||
|
||
return clt, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably clt does not support closing directly, but underlying netConn does, so you can return it here with clt explicitly and call AddCloser to close the connection when session ends
lib/web/sessions.go
Outdated
@@ -158,6 +265,12 @@ func (c *SessionContext) Close() error { | |||
if c.clt != nil { | |||
return trace.Wrap(c.clt.Close()) | |||
} | |||
for _, remoteClt := range c.remoteClt { | |||
err := remoteClt.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, it does, actually, but does it close underlying netConn?
4afef95
to
444d62e
Compare
Purpose
As covered in, #1223, this PR addresses two issues. The first is the rule names that gate access to various resources. The second is getting a client to a remote auth server with the logged in users role.
Implementation
For the first issue, the following three rules gate access to sessions.
In addition a new endpoint
/events/sesssion
and functionSearchSessionEvents
has been created that can only return events related to session start and end which is used to reconstruct the list of completed sessions.For the second issue, the
Dial
function for areversetunnel.RemoteSite
has been updated to accept a special string@remote-auth-server
which returns a TCP connection to the remote auth server. We then build theauthMethods
for the logged in user and establish a SSH connection and from there an client to the auth server. This way we get a client with the users role instead of the role of the proxy.Related Issues
Fixes #1223