diff --git a/constants.go b/constants.go index 9416eb2d4261d..57161eca4962b 100644 --- a/constants.go +++ b/constants.go @@ -194,6 +194,9 @@ const ( TraitInternalRoleVariable = "{{internal.logins}}" ) +// Root is *nix system administrator account name. +const Root = "root" + // DefaultRole is the name of the default admin role for all local users if // another role is not explicitly assigned (Enterprise only). const AdminRoleName = "admin" diff --git a/lib/auth/auth_with_roles.go b/lib/auth/auth_with_roles.go index 3f43c898489da..c4c50559ab342 100644 --- a/lib/auth/auth_with_roles.go +++ b/lib/auth/auth_with_roles.go @@ -744,6 +744,11 @@ func (a *AuthWithRoles) GetRoles() ([]services.Role, error) { return a.authServer.GetRoles() } +// CreateRole creates a role. +func (a *AuthWithRoles) CreateRole(role services.Role, ttl time.Duration) error { + return trace.BadParameter("not implemented") +} + // UpsertRole creates or updates role func (a *AuthWithRoles) UpsertRole(role services.Role, ttl time.Duration) error { if err := a.action(defaults.Namespace, services.KindRole, services.VerbCreate); err != nil { diff --git a/lib/auth/clt.go b/lib/auth/clt.go index 7b5021cbd7787..ba6fb63339ecd 100644 --- a/lib/auth/clt.go +++ b/lib/auth/clt.go @@ -1309,6 +1309,11 @@ func (c *Client) GetRoles() ([]services.Role, error) { return roles, nil } +// CreateRole creates a role. +func (c *Client) CreateRole(role services.Role, ttl time.Duration) error { + return trace.BadParameter("not implemented") +} + // UpsertRole creates or updates role func (c *Client) UpsertRole(role services.Role, ttl time.Duration) error { data, err := services.GetRoleMarshaler().MarshalRole(role) diff --git a/lib/auth/init.go b/lib/auth/init.go index 47d82152070cf..c4b234d81969b 100644 --- a/lib/auth/init.go +++ b/lib/auth/init.go @@ -25,6 +25,7 @@ import ( "time" "github.com/gravitational/teleport" + "github.com/gravitational/teleport/lib" "github.com/gravitational/teleport/lib/backend" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" @@ -192,12 +193,14 @@ func Init(cfg InitConfig) (*AuthServer, *Identity, error) { log.Infof("[INIT] Created Namespace: %q", defaults.Namespace) // always create a default admin role - defaultRole := services.NewAdminRole() - err = asrv.UpsertRole(defaultRole, backend.Forever) - if err != nil { + defaultRole := services.NewAdminRole(lib.IsEnterprise()) + err = asrv.CreateRole(defaultRole, backend.Forever) + if err != nil && !trace.IsAlreadyExists(err) { return nil, nil, trace.Wrap(err) } - log.Infof("[INIT] Created default Role: %q", defaultRole.GetName()) + if !trace.IsAlreadyExists(err) { + log.Infof("[INIT] Created default admin role: %q", defaultRole.GetName()) + } // generate a user certificate authority if it doesn't exist if _, err := asrv.GetCertAuthority(services.CertAuthID{DomainName: cfg.ClusterName.GetClusterName(), Type: services.UserCA}, false); err != nil { diff --git a/lib/auth/tun_test.go b/lib/auth/tun_test.go index 4826a41b9cf57..1cde6cfae6454 100644 --- a/lib/auth/tun_test.go +++ b/lib/auth/tun_test.go @@ -101,7 +101,7 @@ func (s *TunSuite) SetUpTest(c *C) { c.Assert(err, IsNil) // create the default role - c.Assert(s.a.UpsertRole(services.NewAdminRole(), backend.Forever), IsNil) + c.Assert(s.a.UpsertRole(services.NewAdminRole(false), backend.Forever), IsNil) // set up host private key and certificate c.Assert(s.a.UpsertCertAuthority( diff --git a/lib/services/local/access.go b/lib/services/local/access.go index 164daa7df7b94..e77b632ab1671 100644 --- a/lib/services/local/access.go +++ b/lib/services/local/access.go @@ -62,6 +62,26 @@ func (s *AccessService) GetRoles() ([]services.Role, error) { return out, nil } +// CreateRole creates a role on the backend. +func (s *AccessService) CreateRole(role services.Role, ttl time.Duration) error { + data, err := services.GetRoleMarshaler().MarshalRole(role) + if err != nil { + return trace.Wrap(err) + } + + // TODO(klizhentas): Picking smaller of the two ttls + backendTTL := backend.TTL(s.Clock(), role.Expiry()) + if backendTTL < ttl { + ttl = backendTTL + } + + err = s.CreateVal([]string{"roles", role.GetName()}, "params", []byte(data), ttl) + if err != nil { + return trace.Wrap(err) + } + return nil +} + // UpsertRole updates parameters about role func (s *AccessService) UpsertRole(role services.Role, ttl time.Duration) error { data, err := services.GetRoleMarshaler().MarshalRole(role) diff --git a/lib/services/role.go b/lib/services/role.go index 00830875cfdf9..faa9d528e278a 100644 --- a/lib/services/role.go +++ b/lib/services/role.go @@ -79,8 +79,8 @@ func RoleNameForCertAuthority(name string) string { // NewAdminRole is the default admin role for all local users if another role // is not explicitly assigned (Enterprise only). -func NewAdminRole() Role { - return &RoleV3{ +func NewAdminRole(isEnterprise bool) Role { + role := &RoleV3{ Kind: KindRole, Version: V3, Metadata: Metadata{ @@ -93,12 +93,20 @@ func NewAdminRole() Role { }, Allow: RoleConditions{ Namespaces: []string{defaults.Namespace}, - Logins: []string{teleport.TraitInternalRoleVariable}, NodeLabels: map[string]string{Wildcard: Wildcard}, Rules: CopyRulesSlice(AdminUserRules), }, }, } + + // the default role also has "root" for enterprise users + allowedLogins := []string{teleport.TraitInternalRoleVariable} + if isEnterprise { + allowedLogins = append(allowedLogins, teleport.Root) + } + role.SetLogins(Allow, allowedLogins) + + return role } // NewImplicitRole is the default implicit role that gets added to all @@ -181,6 +189,9 @@ type Access interface { // GetRoles returns a list of roles GetRoles() ([]Role, error) + // CreateRole creates a role + CreateRole(role Role, ttl time.Duration) error + // UpsertRole creates or updates role UpsertRole(role Role, ttl time.Duration) error diff --git a/lib/web/apiserver_test.go b/lib/web/apiserver_test.go index 93d16f5d4c78a..9534c882d4831 100644 --- a/lib/web/apiserver_test.go +++ b/lib/web/apiserver_test.go @@ -189,7 +189,7 @@ func (s *WebSuite) SetUpTest(c *C) { c.Assert(err, IsNil) // create the default role - c.Assert(s.authServer.UpsertRole(services.NewAdminRole(), backend.Forever), IsNil) + c.Assert(s.authServer.UpsertRole(services.NewAdminRole(false), backend.Forever), IsNil) // configure cluster authentication preferences cap, err := services.NewAuthPreference(services.AuthPreferenceSpecV2{