Skip to content
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

Creates preset roles v6.0 backport #5968

Merged
merged 1 commit into from
Mar 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,9 +556,23 @@ const SCP = "scp"
const Root = "root"

// AdminRoleName is the name of the default admin role for all local users if
// another role is not explicitly assigned (Enterprise only).
// another role is not explicitly assigned
const AdminRoleName = "admin"

const (
// PresetEditorRoleName is a name of a preset role that allows
// editing cluster configuration.
PresetEditorRoleName = "editor"

// PresetAccessRoleName is a name of a preset role that allows
// accessing cluster resources.
PresetAccessRoleName = "access"

// PresetAuditorRoleName is a name of a preset role that allows
// reading cluster events and playing back session records.
PresetAuditorRoleName = "auditor"
)

// OSSMigratedV6 is a label to mark migrated OSS users and resources
const OSSMigratedV6 = "migrate-v6.0"

Expand Down
2 changes: 1 addition & 1 deletion docs/pages/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ SSH hosts as any of the principals `root`, `ubuntu` or `ec2-user`.

```bash
# tctl is an administrative tool that is used to configure Teleport's auth service.
sudo tctl users add teleport-admin root,ubuntu,ec2-user
sudo tctl users add teleport-admin --roles=editor,access --logins=root,ubuntu,ec2-user
```

Teleport will always enforce the use of 2-factor authentication by default. It supports one-time
Expand Down
23 changes: 23 additions & 0 deletions lib/auth/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,12 @@ func Init(cfg InitConfig, opts ...ServerOption) (*Server, error) {
return nil, trace.Wrap(err)
}

// Create presets - convenience and example resources.
err = createPresets(ctx, asrv)
if err != nil {
return nil, trace.Wrap(err)
}

if !cfg.SkipPeriodicOperations {
log.Infof("Auth server is running periodic operations.")
go asrv.runPeriodicOperations()
Expand Down Expand Up @@ -500,6 +506,23 @@ func migrateLegacyResources(ctx context.Context, cfg InitConfig, asrv *Server) e
return nil
}

// createPresets creates preset resources - roles
func createPresets(ctx context.Context, asrv *Server) error {
roles := []services.Role{
services.NewPresetEditorRole(),
services.NewPresetAccessRole(),
services.NewPresetAuditorRole()}
for _, role := range roles {
err := asrv.CreateRole(role)
if err != nil {
if !trace.IsAlreadyExists(err) {
return trace.Wrap(err, "failed to create preset role")
}
}
}
return nil
}

const migrationAbortedMessage = "migration to RBAC has aborted because of the backend error, restart teleport to try again"

// migrateOSS performs migration to enable role-based access controls
Expand Down
53 changes: 53 additions & 0 deletions lib/auth/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,59 @@ func TestMigrateMFADevices(t *testing.T) {
require.Empty(t, cmp.Diff(users, wantUsers, cmpOpts...))
}

// TestPresets tests behavior of presets
func TestPresets(t *testing.T) {
ctx := context.Background()
roles := []services.Role{
services.NewPresetEditorRole(),
services.NewPresetAccessRole(),
services.NewPresetAuditorRole()}

t.Run("EmptyCluster", func(t *testing.T) {
as := newTestAuthServer(t)
clock := clockwork.NewFakeClock()
as.SetClock(clock)

err := createPresets(ctx, as)
require.NoError(t, err)

// Second call should not fail
err = createPresets(ctx, as)
require.NoError(t, err)

// Presets were created
for _, role := range roles {
_, err := as.GetRole(role.GetName())
require.NoError(t, err)
}
})

// Makes sure that existing role with the same name is not modified
t.Run("ExistingRole", func(t *testing.T) {
as := newTestAuthServer(t)
clock := clockwork.NewFakeClock()
as.SetClock(clock)

access := services.NewPresetEditorRole()
access.SetLogins(types.Allow, []string{"root"})
err := as.CreateRole(access)
require.NoError(t, err)

err = createPresets(ctx, as)
require.NoError(t, err)

// Presets were created
for _, role := range roles {
_, err := as.GetRole(role.GetName())
require.NoError(t, err)
}

out, err := as.GetRole(access.GetName())
require.NoError(t, err)
require.Equal(t, access.GetLogins(types.Allow), out.GetLogins(types.Allow))
})
}

// TestMigrateOSS tests migration of OSS users, github connectors
// and trusted clusters
func TestMigrateOSS(t *testing.T) {
Expand Down
138 changes: 138 additions & 0 deletions lib/services/presets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
Copyright 2021 Gravitational, Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package services

import (
"github.com/gravitational/teleport"

"github.com/gravitational/teleport/lib/defaults"
"github.com/pborman/uuid"
)

// NewPresetEditorRole returuns new pre-defined role for cluster
// editors who can edit cluster configuration resources.
func NewPresetEditorRole() Role {
role := &RoleV3{
Kind: KindRole,
Version: V3,
Metadata: Metadata{
Name: teleport.PresetEditorRoleName,
Namespace: defaults.Namespace,
Description: "Edit cluster configuration",
},
Spec: RoleSpecV3{
Options: RoleOptions{
CertificateFormat: teleport.CertificateFormatStandard,
MaxSessionTTL: NewDuration(defaults.MaxCertDuration),
PortForwarding: NewBoolOption(true),
ForwardAgent: NewBool(true),
BPF: defaults.EnhancedEvents(),
},
Allow: RoleConditions{
Namespaces: []string{defaults.Namespace},
Rules: []Rule{
NewRule(KindUser, RW()),
NewRule(KindRole, RW()),
NewRule(KindOIDC, RW()),
NewRule(KindSAML, RW()),
NewRule(KindGithub, RW()),
NewRule(KindClusterAuthPreference, RW()),
NewRule(KindClusterConfig, RW()),
NewRule(KindTrustedCluster, RW()),
NewRule(KindRemoteCluster, RW()),
},
},
},
}
return role
}

// NewPresetAccessRole creates a role for users who are allowed to initiate
// interactive sessions.
func NewPresetAccessRole() Role {
role := &RoleV3{
Kind: KindRole,
Version: V3,
Metadata: Metadata{
Name: teleport.PresetAccessRoleName,
Namespace: defaults.Namespace,
Description: "Access cluster resources",
},
Spec: RoleSpecV3{
Options: RoleOptions{
CertificateFormat: teleport.CertificateFormatStandard,
MaxSessionTTL: NewDuration(defaults.MaxCertDuration),
PortForwarding: NewBoolOption(true),
ForwardAgent: NewBool(true),
BPF: defaults.EnhancedEvents(),
},
Allow: RoleConditions{
Namespaces: []string{defaults.Namespace},
NodeLabels: Labels{Wildcard: []string{Wildcard}},
AppLabels: Labels{Wildcard: []string{Wildcard}},
KubernetesLabels: Labels{Wildcard: []string{Wildcard}},
DatabaseLabels: Labels{Wildcard: []string{Wildcard}},
DatabaseNames: []string{teleport.TraitInternalDBNamesVariable},
DatabaseUsers: []string{teleport.TraitInternalDBUsersVariable},
Rules: []Rule{
NewRule(KindEvent, RO()),
},
},
},
}
role.SetLogins(Allow, []string{teleport.TraitInternalLoginsVariable})
role.SetKubeUsers(Allow, []string{teleport.TraitInternalKubeUsersVariable})
role.SetKubeGroups(Allow, []string{teleport.TraitInternalKubeGroupsVariable})
return role
}

// NewPresetAuditorRole returuns new pre-defined role for cluster
// auditor - someone who can review cluster events and replay sessions,
// but can't initiate interactive sessions or modify configuration.
func NewPresetAuditorRole() Role {
role := &RoleV3{
Kind: KindRole,
Version: V3,
Metadata: Metadata{
Name: teleport.PresetAuditorRoleName,
Namespace: defaults.Namespace,
Description: "Review cluster events and replay sessions",
},
Spec: RoleSpecV3{
Options: RoleOptions{
CertificateFormat: teleport.CertificateFormatStandard,
MaxSessionTTL: NewDuration(defaults.MaxCertDuration),
},
Allow: RoleConditions{
Namespaces: []string{defaults.Namespace},
Rules: []Rule{
NewRule(KindSession, RO()),
NewRule(KindEvent, RO()),
},
},
Deny: RoleConditions{
Namespaces: []string{Wildcard},
NodeLabels: Labels{Wildcard: []string{Wildcard}},
AppLabels: Labels{Wildcard: []string{Wildcard}},
KubernetesLabels: Labels{Wildcard: []string{Wildcard}},
DatabaseLabels: Labels{Wildcard: []string{Wildcard}},
},
},
}
role.SetLogins(Allow, []string{"no-login-" + uuid.New()})
return role
}