-
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
[v10] Connect: Fetch correct role set when listing db users (#13790) #13877
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ import ( | |
"github.com/gravitational/teleport/api/client/proto" | ||
"github.com/gravitational/teleport/api/defaults" | ||
"github.com/gravitational/teleport/api/types" | ||
"github.com/gravitational/teleport/lib/auth" | ||
"github.com/gravitational/teleport/lib/client" | ||
dbprofile "github.com/gravitational/teleport/lib/client/db" | ||
libdefaults "github.com/gravitational/teleport/lib/defaults" | ||
|
@@ -152,17 +153,33 @@ func (c *Cluster) ReissueDBCerts(ctx context.Context, user, dbName string, db ty | |
|
||
// GetAllowedDatabaseUsers returns allowed users for the given database based on the role set. | ||
func (c *Cluster) GetAllowedDatabaseUsers(ctx context.Context, dbURI string) ([]string, error) { | ||
var roleSet services.RoleSet | ||
var err error | ||
var authClient auth.ClientI | ||
|
||
err = addMetadataToRetryableError(ctx, func() error { | ||
roleSet, err = services.FetchRoles(c.status.Roles, c.clusterClient, c.status.Traits) | ||
return err | ||
err := addMetadataToRetryableError(ctx, func() error { | ||
proxyClient, err := c.clusterClient.ConnectToProxy(ctx) | ||
if err != nil { | ||
return trace.Wrap(err) | ||
} | ||
defer proxyClient.Close() | ||
|
||
authClient, err = proxyClient.ConnectToCluster(ctx, c.clusterClient.SiteName) | ||
if err != nil { | ||
return trace.Wrap(err) | ||
} | ||
|
||
return nil | ||
}) | ||
if err != nil { | ||
return nil, trace.Wrap(err) | ||
} | ||
|
||
defer authClient.Close() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need a nil check here, or is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is guaranteed to be initialized? If the function passed to |
||
|
||
roleSet, err := services.FetchAllClusterRoles(ctx, authClient, c.status.Roles, c.status.Traits) | ||
if err != nil { | ||
return nil, trace.Wrap(err) | ||
} | ||
|
||
db, err := c.GetDatabase(ctx, dbURI) | ||
if err != nil { | ||
return nil, trace.Wrap(err) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,7 +32,7 @@ type Config struct { | |
// InsecureSkipVerify is an option to skip TLS cert check | ||
InsecureSkipVerify bool | ||
// Log is a component logger | ||
Log logrus.FieldLogger | ||
Log *logrus.Entry | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's wrong with using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, that was because initially I was passing |
||
} | ||
|
||
// CheckAndSetDefaults checks the configuration for its validity and sets default values if needed | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,6 @@ limitations under the License. | |
package main | ||
|
||
import ( | ||
"context" | ||
"encoding/base64" | ||
"fmt" | ||
"net" | ||
|
@@ -28,7 +27,6 @@ import ( | |
"github.com/gravitational/teleport" | ||
"github.com/gravitational/teleport/api/client/proto" | ||
"github.com/gravitational/teleport/api/types" | ||
"github.com/gravitational/teleport/lib/auth" | ||
"github.com/gravitational/teleport/lib/client" | ||
dbprofile "github.com/gravitational/teleport/lib/client/db" | ||
"github.com/gravitational/teleport/lib/client/db/dbcmd" | ||
|
@@ -80,7 +78,7 @@ func onListDatabases(cf *CLIConf) error { | |
return trace.Wrap(err) | ||
} | ||
|
||
roleSet, err := fetchRoleSet(cf.Context, cluster, profile) | ||
roleSet, err := services.FetchAllClusterRoles(cf.Context, cluster, profile.Roles, profile.Traits) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rosstimothy do you foresee any performance issues with this approach? |
||
if err != nil { | ||
log.Debugf("Failed to fetch user roles: %v.", err) | ||
} | ||
|
@@ -143,7 +141,7 @@ func listDatabasesAllClusters(cf *CLIConf) error { | |
continue | ||
} | ||
|
||
roleSet, err := fetchRoleSet(cf.Context, cluster, profile) | ||
roleSet, err := services.FetchAllClusterRoles(cf.Context, cluster, profile.Roles, profile.Traits) | ||
if err != nil { | ||
log.Debugf("Failed to fetch user roles: %v.", err) | ||
} | ||
|
@@ -815,32 +813,6 @@ func isMFADatabaseAccessRequired(cf *CLIConf, tc *client.TeleportClient, databas | |
return mfaResp.GetRequired(), nil | ||
} | ||
|
||
// fetchRoleSet fetches a user's roles for a specified cluster. | ||
func fetchRoleSet(ctx context.Context, cluster auth.ClientI, profile *client.ProfileStatus) (services.RoleSet, error) { | ||
// get roles and traits. default to the set from profile, try to get up-to-date version from server point of view. | ||
roles := profile.Roles | ||
traits := profile.Traits | ||
|
||
// GetCurrentUser() may not be implemented, fail gracefully. | ||
user, err := cluster.GetCurrentUser(ctx) | ||
if err == nil { | ||
roles = user.GetRoles() | ||
traits = user.GetTraits() | ||
} else { | ||
log.Debugf("Failed to fetch current user information: %v.", err) | ||
} | ||
|
||
// get the role definition for all roles of user. | ||
// this may only fail if the role which we are looking for does not exist, or we don't have access to it. | ||
// example scenario when this may happen: | ||
// 1. we have set of roles [foo bar] from profile. | ||
// 2. the cluster is remote and maps the [foo, bar] roles to single role [guest] | ||
// 3. the remote cluster doesn't implement GetCurrentUser(), so we have no way to learn of [guest]. | ||
// 4. services.FetchRoles([foo bar], ..., ...) fails as [foo bar] does not exist on remote cluster. | ||
roleSet, err := services.FetchRoles(roles, cluster, traits) | ||
return roleSet, trace.Wrap(err) | ||
} | ||
|
||
// pickActiveDatabase returns the database the current profile is logged into. | ||
// | ||
// If logged into multiple databases, returns an error unless one specified | ||
|
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.
nit
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.
Thanks, I'll push a PR for that tomorrow.