mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-28 03:19:47 +08:00
Add OSS support for kubernetes groups
* Add k8s-groups flag for tctl users add * Add kubernetes_groups field in github connector
This commit is contained in:
committed by
Alexander Klizhentas
parent
bdb3f0608d
commit
43cb9559a5
+10
-2
@@ -325,9 +325,17 @@ const (
|
||||
// allowed logins.
|
||||
TraitLogins = "logins"
|
||||
|
||||
// TraitInternalRoleVariable is the role variable used to store allowed
|
||||
// TraitKubeGroups is the name the role variable used to store
|
||||
// allowed kubernetes groups
|
||||
TraitKubeGroups = "kubernetes_groups"
|
||||
|
||||
// TraitInternalLoginsVariable is the variable used to store allowed
|
||||
// logins for local accounts.
|
||||
TraitInternalRoleVariable = "{{internal.logins}}"
|
||||
TraitInternalLoginsVariable = "{{internal.logins}}"
|
||||
|
||||
// TraitInternalKubeGroupsVariable is the variable used to store allowed
|
||||
// kubernetes groups for local accounts.
|
||||
TraitInternalKubeGroupsVariable = "{{internal.kubernetes_groups}}"
|
||||
)
|
||||
|
||||
// SCP is Secure Copy.
|
||||
|
||||
+1
-1
Submodule e updated: a9c7730334...1984ef6ee7
@@ -32,6 +32,7 @@ import (
|
||||
"github.com/gravitational/teleport/lib/backend/boltbk"
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/fixtures"
|
||||
"github.com/gravitational/teleport/lib/modules"
|
||||
"github.com/gravitational/teleport/lib/services"
|
||||
"github.com/gravitational/teleport/lib/services/suite"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
@@ -612,6 +613,28 @@ func (s *AuthSuite) TestMigrateIdentity(c *C) {
|
||||
fixtures.DeepCompare(c, newid, oldid)
|
||||
}
|
||||
|
||||
// TestMigrateAdminRole tests migration of the admin role
|
||||
func (s *AuthSuite) TestMigrateAdminRole(c *C) {
|
||||
defaultRole := services.NewAdminRole()
|
||||
defaultRole.SetKubeGroups(services.Allow, nil)
|
||||
err := s.a.UpsertRole(defaultRole, backend.Forever)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
err = migrateAdminRole(s.a)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
out, err := s.a.GetRole(defaultRole.GetName())
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(out.GetKubeGroups(services.Allow), DeepEquals, modules.GetModules().DefaultKubeGroups())
|
||||
|
||||
// second call does nothing
|
||||
err = migrateAdminRole(s.a)
|
||||
c.Assert(err, IsNil)
|
||||
out, err = s.a.GetRole(defaultRole.GetName())
|
||||
c.Assert(err, IsNil)
|
||||
c.Assert(out.GetKubeGroups(services.Allow), DeepEquals, modules.GetModules().DefaultKubeGroups())
|
||||
}
|
||||
|
||||
// writeKeys saves the key/cert pair for a given domain onto disk. This usually means the
|
||||
// domain trusts us (signed our public key)
|
||||
func writeKeys(dataDir string, id IdentityID, key []byte, sshCert []byte, tlsCert []byte, tlsCACert []byte) error {
|
||||
|
||||
+2
-2
@@ -212,7 +212,7 @@ func (s *AuthServer) validateGithubAuthCallback(q url.Values) (*GithubAuthRespon
|
||||
}
|
||||
|
||||
func (s *AuthServer) createGithubUser(connector services.GithubConnector, claims services.GithubClaims) error {
|
||||
logins := connector.MapClaims(claims)
|
||||
logins, kubeGroups := connector.MapClaims(claims)
|
||||
if len(logins) == 0 {
|
||||
return trace.BadParameter(
|
||||
"user %q does not belong to any teams configured in %q connector",
|
||||
@@ -230,7 +230,7 @@ func (s *AuthServer) createGithubUser(connector services.GithubConnector, claims
|
||||
},
|
||||
Spec: services.UserSpecV2{
|
||||
Roles: modules.GetModules().RolesFromLogins(logins),
|
||||
Traits: modules.GetModules().TraitsFromLogins(logins),
|
||||
Traits: modules.GetModules().TraitsFromLogins(logins, kubeGroups),
|
||||
Expires: s.clock.Now().UTC().Add(defaults.OAuth2TTL),
|
||||
GithubIdentities: []services.ExternalIdentity{{
|
||||
ConnectorID: connector.GetName(),
|
||||
|
||||
@@ -397,6 +397,10 @@ func migrateLegacyResources(cfg InitConfig, asrv *AuthServer) error {
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
err = migrateAdminRole(asrv)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -467,6 +471,20 @@ func migrateUsers(asrv *AuthServer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func migrateAdminRole(asrv *AuthServer) error {
|
||||
defaultRole := services.NewAdminRole()
|
||||
role, err := asrv.GetRole(defaultRole.GetName())
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
}
|
||||
if len(role.GetKubeGroups(services.Allow)) != 0 {
|
||||
return nil
|
||||
}
|
||||
log.Infof("Migrating default admin role, adding default kubernetes groups.")
|
||||
role.SetKubeGroups(services.Allow, defaultRole.GetKubeGroups(services.Allow))
|
||||
return asrv.UpsertRole(role, backend.Forever)
|
||||
}
|
||||
|
||||
// isFirstStart returns 'true' if the auth server is starting for the 1st time
|
||||
// on this server.
|
||||
func isFirstStart(authServer *AuthServer, cfg InitConfig) (bool, error) {
|
||||
|
||||
+13
-5
@@ -33,14 +33,16 @@ type Modules interface {
|
||||
EmptyRolesHandler() error
|
||||
// DefaultAllowedLogins returns default allowed logins for a new admin role
|
||||
DefaultAllowedLogins() []string
|
||||
// DefaultKubeGroups returns default kuberentes groups for a new admin role
|
||||
DefaultKubeGroups() []string
|
||||
// PrintVersion prints teleport version
|
||||
PrintVersion()
|
||||
// RolesFromLogins returns roles for external user based on the logins
|
||||
// extracted from the connector
|
||||
RolesFromLogins([]string) []string
|
||||
// TraitsFromLogins returns traits for external user based on the logins
|
||||
// extracted from the connector
|
||||
TraitsFromLogins([]string) map[string][]string
|
||||
// and kubernetes groups extracted from the connector
|
||||
TraitsFromLogins([]string, []string) map[string][]string
|
||||
}
|
||||
|
||||
// SetModules sets the modules interface
|
||||
@@ -65,9 +67,14 @@ func (p *defaultModules) EmptyRolesHandler() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultKubeGroups returns default kuberentes groups for a new admin role
|
||||
func (p *defaultModules) DefaultKubeGroups() []string {
|
||||
return []string{teleport.TraitInternalKubeGroupsVariable}
|
||||
}
|
||||
|
||||
// DefaultAllowedLogins returns allowed logins for a new admin role
|
||||
func (p *defaultModules) DefaultAllowedLogins() []string {
|
||||
return []string{teleport.TraitInternalRoleVariable}
|
||||
return []string{teleport.TraitInternalLoginsVariable}
|
||||
}
|
||||
|
||||
// PrintVersion prints teleport version
|
||||
@@ -92,9 +99,10 @@ func (p *defaultModules) RolesFromLogins(logins []string) []string {
|
||||
// extracted from the connector
|
||||
//
|
||||
// By default logins are treated as allowed logins user traits.
|
||||
func (p *defaultModules) TraitsFromLogins(logins []string) map[string][]string {
|
||||
func (p *defaultModules) TraitsFromLogins(logins []string, kubeGroups []string) map[string][]string {
|
||||
return map[string][]string{
|
||||
teleport.TraitLogins: logins,
|
||||
teleport.TraitLogins: logins,
|
||||
teleport.TraitKubeGroups: kubeGroups,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,14 +36,18 @@ func (s *ModulesSuite) TestDefaultModules(c *check.C) {
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
logins := GetModules().DefaultAllowedLogins()
|
||||
c.Assert(logins, check.DeepEquals, []string{teleport.TraitInternalRoleVariable})
|
||||
c.Assert(logins, check.DeepEquals, []string{teleport.TraitInternalLoginsVariable})
|
||||
|
||||
kubeGroups := GetModules().DefaultKubeGroups()
|
||||
c.Assert(kubeGroups, check.DeepEquals, []string{teleport.TraitInternalKubeGroupsVariable})
|
||||
|
||||
roles := GetModules().RolesFromLogins([]string{"root"})
|
||||
c.Assert(roles, check.DeepEquals, []string{teleport.AdminRoleName})
|
||||
|
||||
traits := GetModules().TraitsFromLogins([]string{"root"})
|
||||
traits := GetModules().TraitsFromLogins([]string{"root"}, []string{"system:masters"})
|
||||
c.Assert(traits, check.DeepEquals, map[string][]string{
|
||||
teleport.TraitLogins: []string{"root"},
|
||||
teleport.TraitLogins: []string{"root"},
|
||||
teleport.TraitKubeGroups: []string{"system:masters"},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -59,7 +63,7 @@ func (s *ModulesSuite) TestTestModules(c *check.C) {
|
||||
roles := GetModules().RolesFromLogins([]string{"root"})
|
||||
c.Assert(roles, check.DeepEquals, []string{"root"})
|
||||
|
||||
traits := GetModules().TraitsFromLogins([]string{"root"})
|
||||
traits := GetModules().TraitsFromLogins([]string{"root"}, []string{"system:masters"})
|
||||
c.Assert(traits, check.IsNil)
|
||||
}
|
||||
|
||||
@@ -73,12 +77,16 @@ func (p *testModules) DefaultAllowedLogins() []string {
|
||||
return []string{"a", "b"}
|
||||
}
|
||||
|
||||
func (p *testModules) DefaultKubeGroups() []string {
|
||||
return []string{"kube:test"}
|
||||
}
|
||||
|
||||
func (p *testModules) PrintVersion() {}
|
||||
|
||||
func (p *testModules) RolesFromLogins(logins []string) []string {
|
||||
return logins
|
||||
}
|
||||
|
||||
func (p *testModules) TraitsFromLogins(logins []string) map[string][]string {
|
||||
func (p *testModules) TraitsFromLogins(logins []string, kubeGroups []string) map[string][]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
+17
-6
@@ -51,7 +51,8 @@ type GithubConnector interface {
|
||||
// SetTeamsToLogins sets the mapping of Github teams to allowed logins
|
||||
SetTeamsToLogins([]TeamMapping)
|
||||
// MapClaims returns the list of allows logins based on the retrieved claims
|
||||
MapClaims(GithubClaims) []string
|
||||
// returns list of logins and kubernetes groups
|
||||
MapClaims(GithubClaims) ([]string, []string)
|
||||
// GetDisplay returns the connector display name
|
||||
GetDisplay() string
|
||||
// SetDisplay sets the connector display name
|
||||
@@ -104,7 +105,9 @@ type TeamMapping struct {
|
||||
// Team is a team within the organization a user belongs to
|
||||
Team string `json:"team"`
|
||||
// Logins is a list of allowed logins for this org/team
|
||||
Logins []string `json:"logins"`
|
||||
Logins []string `json:"logins,omitempty"`
|
||||
// KubeGroups is a list of allowed kubernetes groups for this org/team
|
||||
KubeGroups []string `json:"kubernetes_groups,omitempty"`
|
||||
}
|
||||
|
||||
// GithubClaims represents Github user information obtained during OAuth2 flow
|
||||
@@ -203,9 +206,10 @@ func (c *GithubConnectorV3) SetDisplay(display string) {
|
||||
c.Spec.Display = display
|
||||
}
|
||||
|
||||
// MapClaims returns a list of logins based on the provided claims
|
||||
func (c *GithubConnectorV3) MapClaims(claims GithubClaims) []string {
|
||||
var logins []string
|
||||
// MapClaims returns a list of logins based on the provided claims,
|
||||
// returns a list of logins and list of kubernetes groups
|
||||
func (c *GithubConnectorV3) MapClaims(claims GithubClaims) ([]string, []string) {
|
||||
var logins, kubeGroups []string
|
||||
for _, mapping := range c.GetTeamsToLogins() {
|
||||
teams, ok := claims.OrganizationToTeams[mapping.Organization]
|
||||
if !ok {
|
||||
@@ -216,10 +220,11 @@ func (c *GithubConnectorV3) MapClaims(claims GithubClaims) []string {
|
||||
// see if the user belongs to this team
|
||||
if team == mapping.Team {
|
||||
logins = append(logins, mapping.Logins...)
|
||||
kubeGroups = append(kubeGroups, mapping.KubeGroups...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return utils.Deduplicate(logins)
|
||||
return utils.Deduplicate(logins), utils.Deduplicate(kubeGroups)
|
||||
}
|
||||
|
||||
var githubConnectorMarshaler GithubConnectorMarshaler = &TeleportGithubConnectorMarshaler{}
|
||||
@@ -323,6 +328,12 @@ var TeamMappingSchema = `{
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"kubernetes_groups": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}`
|
||||
|
||||
@@ -76,22 +76,37 @@ func (s *GithubSuite) TestMapClaims(c *check.C) {
|
||||
Organization: "gravitational",
|
||||
Team: "admins",
|
||||
Logins: []string{"admin", "dev"},
|
||||
KubeGroups: []string{"system:masters", "kube-devs"},
|
||||
},
|
||||
{
|
||||
Organization: "gravitational",
|
||||
Team: "devs",
|
||||
Logins: []string{"dev", "test"},
|
||||
KubeGroups: []string{"kube-devs"},
|
||||
},
|
||||
},
|
||||
})
|
||||
c.Assert(connector.MapClaims(GithubClaims{
|
||||
logins, kubeGroups := connector.MapClaims(GithubClaims{
|
||||
OrganizationToTeams: map[string][]string{
|
||||
"gravitational": []string{"admins"},
|
||||
},
|
||||
}), check.DeepEquals, []string{"admin", "dev"})
|
||||
c.Assert(connector.MapClaims(GithubClaims{
|
||||
})
|
||||
c.Assert(logins, check.DeepEquals, []string{"admin", "dev"})
|
||||
c.Assert(kubeGroups, check.DeepEquals, []string{"system:masters", "kube-devs"})
|
||||
|
||||
logins, kubeGroups = connector.MapClaims(GithubClaims{
|
||||
OrganizationToTeams: map[string][]string{
|
||||
"gravitational": []string{"devs"},
|
||||
},
|
||||
})
|
||||
c.Assert(logins, check.DeepEquals, []string{"dev", "test"})
|
||||
c.Assert(kubeGroups, check.DeepEquals, []string{"kube-devs"})
|
||||
|
||||
logins, kubeGroups = connector.MapClaims(GithubClaims{
|
||||
OrganizationToTeams: map[string][]string{
|
||||
"gravitational": []string{"admins", "devs"},
|
||||
},
|
||||
}), check.DeepEquals, []string{"admin", "dev", "test"})
|
||||
})
|
||||
c.Assert(logins, check.DeepEquals, []string{"admin", "dev", "test"})
|
||||
c.Assert(kubeGroups, check.DeepEquals, []string{"system:masters", "kube-devs"})
|
||||
}
|
||||
|
||||
@@ -22,10 +22,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gravitational/teleport/lib/defaults"
|
||||
"github.com/gravitational/teleport/lib/fixtures"
|
||||
"github.com/gravitational/teleport/lib/utils"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/kylelemons/godebug/diff"
|
||||
. "gopkg.in/check.v1"
|
||||
)
|
||||
|
||||
@@ -95,6 +94,7 @@ func (s *MigrationsSuite) TestMigrateUsers(c *C) {
|
||||
in := &UserV1{
|
||||
Name: "alice",
|
||||
AllowedLogins: []string{"admin", "centos"},
|
||||
KubeGroups: []string{"system:masters"},
|
||||
OIDCIdentities: []ExternalIdentity{{Username: "alice@example.com", ConnectorID: "example"}},
|
||||
Status: LoginStatus{
|
||||
IsLocked: true,
|
||||
@@ -122,15 +122,16 @@ func (s *MigrationsSuite) TestMigrateUsers(c *C) {
|
||||
Expires: in.Expires,
|
||||
CreatedBy: in.CreatedBy,
|
||||
Traits: map[string][]string{
|
||||
"logins": in.AllowedLogins,
|
||||
"logins": in.AllowedLogins,
|
||||
"kubernetes_groups": in.KubeGroups,
|
||||
},
|
||||
},
|
||||
rawObject: *in,
|
||||
}
|
||||
c.Assert(out.rawObject, DeepEquals, *in)
|
||||
c.Assert(out.Metadata, DeepEquals, expected.Metadata)
|
||||
c.Assert(out.Spec, DeepEquals, expected.Spec)
|
||||
c.Assert(out, DeepEquals, expected)
|
||||
fixtures.DeepCompare(c, out.rawObject, *in)
|
||||
fixtures.DeepCompare(c, out.Metadata, expected.Metadata)
|
||||
fixtures.DeepCompare(c, out.Spec, expected.Spec)
|
||||
fixtures.DeepCompare(c, out, expected)
|
||||
|
||||
data, err := json.Marshal(in)
|
||||
c.Assert(err, IsNil)
|
||||
@@ -144,11 +145,10 @@ func (s *MigrationsSuite) TestMigrateUsers(c *C) {
|
||||
out3, err := GetUserMarshaler().UnmarshalUser(data)
|
||||
c.Assert(err, IsNil)
|
||||
|
||||
d := &spew.ConfigState{Indent: " ", DisableMethods: true, DisablePointerMethods: true, DisablePointerAddresses: true}
|
||||
expected.rawObject = nil
|
||||
obj := out3.(*UserV2)
|
||||
obj.rawObject = nil
|
||||
c.Assert(obj, DeepEquals, expected, Commentf("%v", diff.Diff(d.Sdump(obj), d.Sdump(expected))))
|
||||
fixtures.DeepCompare(c, obj, expected)
|
||||
|
||||
// test backwards compatibility
|
||||
data, err = GetUserMarshaler().MarshalUser(expected, WithVersion(V1))
|
||||
@@ -156,7 +156,8 @@ func (s *MigrationsSuite) TestMigrateUsers(c *C) {
|
||||
var out4 UserV1
|
||||
json.Unmarshal(data, &out4)
|
||||
in.AllowedLogins = nil
|
||||
c.Assert(out4, DeepEquals, *in, Commentf("%v", diff.Diff(d.Sdump(obj), d.Sdump(*in))))
|
||||
in.KubeGroups = nil
|
||||
fixtures.DeepCompare(c, out4, *in)
|
||||
}
|
||||
|
||||
func (s *MigrationsSuite) TestMigrateReverseTunnels(c *C) {
|
||||
|
||||
@@ -104,6 +104,7 @@ func NewAdminRole() Role {
|
||||
},
|
||||
}
|
||||
role.SetLogins(Allow, modules.GetModules().DefaultAllowedLogins())
|
||||
role.SetKubeGroups(Allow, modules.GetModules().DefaultKubeGroups())
|
||||
return role
|
||||
}
|
||||
|
||||
@@ -354,9 +355,9 @@ func applyValueTraits(val string, traits map[string][]string) ([]string, error)
|
||||
return []string{val}, nil
|
||||
}
|
||||
|
||||
// For internal traits, only internal.logins is supported at the moment.
|
||||
// For internal traits, only internal.logins and internal.kubernetes_groups is supported at the moment.
|
||||
if variablePrefix == teleport.TraitInternalPrefix {
|
||||
if variableName != teleport.TraitLogins {
|
||||
if variableName != teleport.TraitLogins && variableName != teleport.TraitKubeGroups {
|
||||
return nil, trace.BadParameter("unsupported variable %q", variableName)
|
||||
}
|
||||
}
|
||||
@@ -701,7 +702,7 @@ type RoleConditions struct {
|
||||
Rules []Rule `json:"rules,omitempty"`
|
||||
|
||||
// KubeGroups is a list of kubernetes groups
|
||||
KubeGroups []string `json:"kube_groups,omitempty"`
|
||||
KubeGroups []string `json:"kubernetes_groups,omitempty"`
|
||||
}
|
||||
|
||||
// Equals returns true if the role conditions (logins, namespaces, labels,
|
||||
@@ -1894,7 +1895,7 @@ const RoleSpecV3SchemaDefinitions = `
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"kube_groups": {
|
||||
"kubernetes_groups": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
|
||||
@@ -681,6 +681,7 @@ func (s *ServicesTestSuite) GithubConnectorCRUD(c *C) {
|
||||
Organization: "gravitational",
|
||||
Team: "admins",
|
||||
Logins: []string{"admin"},
|
||||
KubeGroups: []string{"system:masters"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -475,6 +475,10 @@ type UserV1 struct {
|
||||
// user is allowed to login as
|
||||
AllowedLogins []string `json:"allowed_logins"`
|
||||
|
||||
// KubeGroups represents a list of kubernetes groups
|
||||
// this teleport user is allowed to assume
|
||||
KubeGroups []string `json:"kubernetes_groups,omitempty"`
|
||||
|
||||
// OIDCIdentities lists associated OpenID Connect identities
|
||||
// that let user log in using externally verified identity
|
||||
OIDCIdentities []ExternalIdentity `json:"oidc_identities"`
|
||||
@@ -532,7 +536,8 @@ func (u *UserV1) V2() *UserV2 {
|
||||
CreatedBy: u.CreatedBy,
|
||||
Roles: u.Roles,
|
||||
Traits: map[string][]string{
|
||||
teleport.TraitLogins: u.AllowedLogins,
|
||||
teleport.TraitLogins: u.AllowedLogins,
|
||||
teleport.TraitKubeGroups: u.KubeGroups,
|
||||
},
|
||||
},
|
||||
rawObject: *u,
|
||||
|
||||
@@ -38,6 +38,7 @@ type UserCommand struct {
|
||||
config *service.Config
|
||||
login string
|
||||
allowedLogins string
|
||||
kubeGroups string
|
||||
roles string
|
||||
identities []string
|
||||
ttl time.Duration
|
||||
@@ -57,6 +58,8 @@ func (u *UserCommand) Initialize(app *kingpin.Application, config *service.Confi
|
||||
u.userAdd.Arg("account", "Teleport user account name").Required().StringVar(&u.login)
|
||||
u.userAdd.Arg("local-logins", "Local UNIX users this account can log in as [login]").
|
||||
Default("").StringVar(&u.allowedLogins)
|
||||
u.userAdd.Flag("k8s-groups", "Kubernetes groups to assign to a user.").
|
||||
Default("").StringVar(&u.kubeGroups)
|
||||
u.userAdd.Flag("ttl", fmt.Sprintf("Set expiration time for token, default is %v hour, maximum is %v hours",
|
||||
int(defaults.SignupTokenTTL/time.Hour), int(defaults.MaxSignupTokenTTL/time.Hour))).
|
||||
Default(fmt.Sprintf("%v", defaults.SignupTokenTTL)).DurationVar(&u.ttl)
|
||||
@@ -98,9 +101,14 @@ func (u *UserCommand) Add(client auth.ClientI) error {
|
||||
if u.allowedLogins == "" {
|
||||
u.allowedLogins = u.login
|
||||
}
|
||||
var kubeGroups []string
|
||||
if u.kubeGroups != "" {
|
||||
kubeGroups = strings.Split(u.kubeGroups, ",")
|
||||
}
|
||||
user := services.UserV1{
|
||||
Name: u.login,
|
||||
AllowedLogins: strings.Split(u.allowedLogins, ","),
|
||||
KubeGroups: kubeGroups,
|
||||
}
|
||||
token, err := client.CreateSignupToken(user, u.ttl)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user