diff --git a/lib/auth/github.go b/lib/auth/github.go index b430ba129654f..a447f9dca3594 100644 --- a/lib/auth/github.go +++ b/lib/auth/github.go @@ -878,6 +878,9 @@ type CreateUserParams struct { // Username is the Teleport user name . Username string + // UserID is the unique ID of the GitHub user. + UserID string + // KubeGroups is the list of Kubernetes groups this user belongs to. KubeGroups []string @@ -898,6 +901,7 @@ func (a *Server) calculateGithubUser(ctx context.Context, diagCtx *SSODiagContex p := CreateUserParams{ ConnectorName: connector.GetName(), Username: claims.Username, + UserID: claims.UserID, } // Calculate logins, kubegroups, roles, and traits. @@ -961,6 +965,7 @@ func (a *Server) createGithubUser(ctx context.Context, p *CreateUserParams, dryR GithubIdentities: []types.ExternalIdentity{{ ConnectorID: p.ConnectorName, Username: p.Username, + UserID: p.UserID, }}, CreatedBy: types.CreatedBy{ User: types.UserRef{Name: teleport.UserSystem}, diff --git a/lib/auth/gitserver/gitserverv1/github.go b/lib/auth/gitserver/gitserverv1/github.go index a828d3394ecf9..17aaa60436c67 100644 --- a/lib/auth/gitserver/gitserverv1/github.go +++ b/lib/auth/gitserver/gitserverv1/github.go @@ -39,6 +39,12 @@ func (s *Service) CreateGitHubAuthRequest(ctx context.Context, in *pb.CreateGitH if err := types.ValidateGitHubOrganizationName(in.Organization); err != nil { return nil, trace.Wrap(err) } + if in.Request.SSOTestFlow { + return nil, trace.BadParameter("sso test flow is not supported when creating GitHub auth request for authenticated user") + } + if in.Request.CreateWebSession { + return nil, trace.BadParameter("CreateWebSession is not supported when creating GitHub auth request for authenticated user") + } authCtx, gitServer, err := s.authAndFindServerByOrg(ctx, in.Organization) if err != nil { diff --git a/lib/client/profile.go b/lib/client/profile.go index ebae1a5ed0b92..985266ee3bc75 100644 --- a/lib/client/profile.go +++ b/lib/client/profile.go @@ -255,7 +255,9 @@ type ProfileStatus struct { // GitHubIdentity is the GitHub identity attached to the user. type GitHubIdentity struct { - UserID string + // UserID is the unique ID of the GitHub user. + UserID string + // Username is the GitHub username. Username string } diff --git a/tool/tsh/common/git_list.go b/tool/tsh/common/git_list.go index 2e70b534565bc..dc7838af2c70f 100644 --- a/tool/tsh/common/git_list.go +++ b/tool/tsh/common/git_list.go @@ -134,12 +134,20 @@ func printGitServers(cf *CLIConf, servers []types.Server) error { func printGitServersAsText(cf *CLIConf, servers []types.Server) error { var rows [][]string var showLoginNote bool + profileStatus, err := cf.ProfileStatus() + if err != nil { + return trace.Wrap(err) + } for _, server := range servers { - // TODO(greedy52) fill in GitHub login when available from Profile. login := "(n/a)*" - showLoginNote = true if github := server.GetGitHub(); github != nil { + if profileStatus.GitHubIdentity != nil { + login = profileStatus.GitHubIdentity.Username + } else { + showLoginNote = true + } + rows = append(rows, []string{ "GitHub", github.Organization, diff --git a/tool/tsh/common/git_list_test.go b/tool/tsh/common/git_list_test.go index 071bf0765e61e..d2f038db13775 100644 --- a/tool/tsh/common/git_list_test.go +++ b/tool/tsh/common/git_list_test.go @@ -50,6 +50,7 @@ func TestGitListCommand(t *testing.T) { name string format string fetchFn func(*CLIConf, *client.TeleportClient) ([]types.Server, error) + profileStatus *client.ProfileStatus wantError bool containsOutput []string }{ @@ -65,12 +66,30 @@ func TestGitListCommand(t *testing.T) { fetchFn: func(c *CLIConf, client *client.TeleportClient) ([]types.Server, error) { return []types.Server{server1, server2}, nil }, + profileStatus: &client.ProfileStatus{}, containsOutput: []string{ "Type Organization Username URL", "GitHub org1 (n/a)* https://github.com/org1", "GitHub org2 (n/a)* https://github.com/org2", }, }, + { + name: "text format with GitHub identity", + fetchFn: func(c *CLIConf, client *client.TeleportClient) ([]types.Server, error) { + return []types.Server{server1, server2}, nil + }, + profileStatus: &client.ProfileStatus{ + GitHubIdentity: &client.GitHubIdentity{ + UserID: "1234567", + Username: "wow", + }, + }, + containsOutput: []string{ + "Type Organization Username URL", + "GitHub org1 wow https://github.com/org1", + "GitHub org2 wow https://github.com/org2", + }, + }, { name: "json format", format: "json", @@ -101,10 +120,11 @@ func TestGitListCommand(t *testing.T) { t.Run(test.name, func(t *testing.T) { var capture bytes.Buffer cf := &CLIConf{ - Proxy: "proxy", - Username: "alice", - OverrideStdout: &capture, - HomePath: t.TempDir(), + Proxy: "proxy", + Username: "alice", + OverrideStdout: &capture, + HomePath: t.TempDir(), + profileStatusOverride: test.profileStatus, } // Create a empty profile so we don't ping proxy.