Skip to content

Commit

Permalink
Add reviewer and requester roles. (#28076)
Browse files Browse the repository at this point in the history
Reviewer and requester roles have been added to allow for easy defaults for
reviewing and requesting applications and user groups for the Okta service.
  • Loading branch information
mdwn committed Jun 20, 2023
1 parent d4211a1 commit c9d04ff
Show file tree
Hide file tree
Showing 34 changed files with 1,241 additions and 93 deletions.
2 changes: 2 additions & 0 deletions api/proto/teleport/legacy/types/types.proto
Expand Up @@ -2724,6 +2724,7 @@ message SessionJoinPolicy {

// AccessRequestConditions is a matcher for allow/deny restrictions on
// access-requests.
// Please remember to update IsEmpty when updating this message.
message AccessRequestConditions {
// Roles is the name of roles which will match the request rule.
repeated string Roles = 1 [(gogoproto.jsontag) = "roles,omitempty"];
Expand Down Expand Up @@ -2768,6 +2769,7 @@ message AccessRequestConditions {

// AccessReviewConditions is a matcher for allow/deny restrictions on
// access reviews.
// Please remember to update IsEmpty when updating this message.
message AccessReviewConditions {
// Roles is the name of roles which may be reviewed.
repeated string Roles = 1 [(gogoproto.jsontag) = "roles,omitempty"];
Expand Down
16 changes: 16 additions & 0 deletions api/types/constants.go
Expand Up @@ -568,6 +568,22 @@ const (
// downgraded before being returned to clients on older versions that do not
// support one or more features enabled in that resource.
TeleportDowngradedLabel = TeleportInternalLabelPrefix + "downgraded"

// TeleportInternalResourceType indicates the type of internal Teleport resource a resource is.
// Valid values are:
// - system: These resources will be automatically created and overwritten on startup. Users should
// not change these resources.
// - preset: These resources will be created if they don't exist. Updates may be applied to them,
// but user changes to these resources will be preserved.
TeleportInternalResourceType = TeleportInternalLabelPrefix + "resource-type"

// SystemResource are resources that will be automatically created and overwritten on startup. Users
// should not change these resources.
SystemResource = "system"

// PresetResource are resources resources will be created if they don't exist. Updates may be applied
// to them, but user changes to these resources will be preserved.
PresetResource = "preset"
)

// CloudHostnameTag is the name of the tag in a cloud instance used to override a node's hostname.
Expand Down
18 changes: 18 additions & 0 deletions api/types/role.go
Expand Up @@ -1655,3 +1655,21 @@ var LabelMatcherKinds = []string{
KindWindowsDesktopService,
KindUserGroup,
}

// IsEmpty will return true if the condition is empty.
func (a AccessRequestConditions) IsEmpty() bool {
return len(a.Annotations) == 0 &&
len(a.ClaimsToRoles) == 0 &&
len(a.Roles) == 0 &&
len(a.SearchAsRoles) == 0 &&
len(a.SuggestedReviewers) == 0 &&
len(a.Thresholds) == 0
}

// IsEmpty will return true if the condition is empty.
func (a AccessReviewConditions) IsEmpty() bool {
return len(a.ClaimsToRoles) == 0 &&
len(a.PreviewAsRoles) == 0 &&
len(a.Roles) == 0 &&
len(a.Where) == 0
}
145 changes: 145 additions & 0 deletions api/types/role_test.go
@@ -0,0 +1,145 @@
/*
Copyright 2023 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 types

import (
"testing"

"github.com/stretchr/testify/require"

"github.com/gravitational/teleport/api/types/wrappers"
)

func TestAccessRequestConditionsIsEmpty(t *testing.T) {
tests := []struct {
name string
arc AccessRequestConditions
expected bool
}{
{
name: "empty",
arc: AccessRequestConditions{},
expected: true,
},
{
name: "annotations",
arc: AccessRequestConditions{
Annotations: wrappers.Traits{
"test": []string{"test"},
},
},
expected: false,
},
{
name: "claims to roles",
arc: AccessRequestConditions{
ClaimsToRoles: []ClaimMapping{
{},
},
},
expected: false,
},
{
name: "roles",
arc: AccessRequestConditions{
Roles: []string{"test"},
},
expected: false,
},
{
name: "search as roles",
arc: AccessRequestConditions{
SearchAsRoles: []string{"test"},
},
expected: false,
},
{
name: "suggested reviewers",
arc: AccessRequestConditions{
SuggestedReviewers: []string{"test"},
},
expected: false,
},
{
name: "thresholds",
arc: AccessRequestConditions{
Thresholds: []AccessReviewThreshold{
{
Name: "test",
},
},
},
expected: false,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
require.Equal(t, test.expected, test.arc.IsEmpty())
})
}
}

func TestAccessReviewConditionsIsEmpty(t *testing.T) {
tests := []struct {
name string
arc AccessReviewConditions
expected bool
}{
{
name: "empty",
arc: AccessReviewConditions{},
expected: true,
},
{
name: "claims to roles",
arc: AccessReviewConditions{
ClaimsToRoles: []ClaimMapping{
{},
},
},
expected: false,
},
{
name: "preview as roles",
arc: AccessReviewConditions{
PreviewAsRoles: []string{"test"},
},
expected: false,
},
{
name: "roles",
arc: AccessReviewConditions{
Roles: []string{"test"},
},
expected: false,
},
{
name: "where",
arc: AccessReviewConditions{
Where: "test",
},
expected: false,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
require.Equal(t, test.expected, test.arc.IsEmpty())
})
}
}
2 changes: 2 additions & 0 deletions api/types/types.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions constants.go
Expand Up @@ -612,6 +612,18 @@ const (
// PresetAuditorRoleName is a name of a preset role that allows
// reading cluster events and playing back session records.
PresetAuditorRoleName = "auditor"

// PresetReviewerRoleName is a name of a preset role that allows
// for reviewing access requests.
PresetReviewerRoleName = "reviewer"

// PresetRequesterRoleName is a name of a preset role that allows
// for requesting access to resources.
PresetRequesterRoleName = "requester"

// PresetGroupAccessRoleName is a name of a preset role that allows
// access to all user groups.
PresetGroupAccessRoleName = "group-access"
)

var PresetRoles = []string{PresetEditorRoleName, PresetAccessRoleName, PresetAuditorRoleName}
Expand Down
1 change: 1 addition & 0 deletions docs/cspell.json
Expand Up @@ -36,6 +36,7 @@
"CLOUDSDK",
"CTAP",
"Cgajq",
"dbreviewer",
"DBSIZE",
"DEBU",
"DHDR",
Expand Down
66 changes: 11 additions & 55 deletions docs/pages/access-controls/access-requests/resource-requests.mdx
Expand Up @@ -39,57 +39,13 @@ It is not recommended to enable Resource Access Requests by setting any
upgraded to version 10.
</Admonition>

## Step 1/8. Create the requester role
## Step 1/6. Grant the reviewer and requester roles to users

This role allows the requester to search for resources accessible by the
`access` role (all resources by default) and request access to them.

```yaml
# requester.yaml
kind: role
version: v5
metadata:
name: requester
spec:
allow:
request:
search_as_roles:
- access
```

```code
$ tctl create requester.yaml
```

## Step 2/8. Create the reviewer role

This role allows the reviewer to approve all requests for the `access` role.

```yaml
# reviewer.yaml
kind: role
version: v5
metadata:
name: reviewer
spec:
allow:
review_requests:
roles:
- access
preview_as_roles:
- access
```

```code
$ tctl create reviewer.yaml
```

## Step 3/8. Grant the roles to users

Grant the `requester` and `reviewer` roles to existing users, or create new
users to test this feature.
Make sure the requester has a valid `login` so that they can view and access SSH
nodes.
Teleport comes with the built-in role `requester`, which allows users to request access
to all resources within Teleport, and `reviewer`, which allows users to review all access
requests within Teleport. To test this feature, grant the built-in `requester` and `reviewer`
roles to existing users, or create new users. Make sure the requester has a valid `login`
so that they can view and access SSH nodes.

```code
$ tctl users add alice --roles requester --logins alice
Expand All @@ -100,7 +56,7 @@ For the rest of the guide we will assume that the `requester` role has been
granted to a user named `alice` and the `reviewer` role has been granted to a
user named `bob`.

## Step 4/8. Search for resources
## Step 2/6. Search for resources

First, log in as `alice`.

Expand Down Expand Up @@ -146,7 +102,7 @@ To request access to these resources, run
--reason <request reason>
```

## Step 5/8. Request access to a resource
## Step 3/6. Request access to a resource

Copy the command output by `tsh request search` in the previous step, optionally filling in a request reason.

Expand All @@ -170,7 +126,7 @@ Waiting for request approval...

The command will automatically wait until the request is approved.

## Step 6/8. Approve the Access Request
## Step 4/6. Approve the Access Request

First, log in as `bob`.

Expand Down Expand Up @@ -210,7 +166,7 @@ Check out our
to notify the right people about new Access Requests.
</Notice>

## Step 7/8. Access the requested resource
## Step 5/6. Access the requested resource

`alice`'s `tsh request create` command should resolve now that the request has been approved.

Expand Down Expand Up @@ -256,7 +212,7 @@ $ tsh ssh alice@iot
iot:~ alice$
```

## Step 8/8. Resume regular access
## Step 6/6. Resume regular access

While logged in with a Resource Access Request, users will be blocked from access to any other resources.
This is necessary because their certificate now contains an elevated role,
Expand Down

0 comments on commit c9d04ff

Please sign in to comment.