Skip to content

Commit

Permalink
docs: Update nested Access List RFD (#47651)
Browse files Browse the repository at this point in the history
- Fixup grammar, typos
- Clarify inheritance and membership/ownership requirements
- Clarify Grant inheritance
  • Loading branch information
kiosion authored Oct 30, 2024
1 parent f078612 commit ff91dc0
Showing 1 changed file with 115 additions and 77 deletions.
192 changes: 115 additions & 77 deletions rfd/0170-nested-accesslists.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,102 +10,141 @@ state: in development
# What

This RFD proposes adding support for including owners and
members in access lists from other access lists
members in Access Lists from other Access Lists

# Why

This allows a hierarchical access list structure for organizations
which is supported by access list implementations being integrated
with, for example Azure Entra supports including groups in other
groups which we want to be able to mimic the structure of in Teleport
access lists.
This allows a hierarchical Access List structure for organizations
which is supported by Access List implementations being integrated
with. For example, Azure Entra supports including groups in other
groups, which we want to be able to mimic the structure of in Teleport
Access Lists.

Users in an access list hierarchy will inherit the granted roles and
traits for members and owners from access lists referencing the lists
they're in.

# Implementation

New fields will be introduced into the access_list type:
The `AccessListMember` type will be modified to include a new field:

```yaml
kind: access_list
metadata:
name: e69aa529-2a7f-4de2-87be-97fd94309a9f
spec:
grants:
roles:
- access
- auditor
traits: {}
dynamic_members:
- access_list_members:
# A user becomes an access list member if its a member of the access list
- ea4cbbc7-bee1-49b3-bf78-734b4b27ea38
dynamic_owners:
access_list_owners:
# A user becomes an access list owner if its a member of the access list
- 3e9df1e7-0b8a-4984-b2e8-5bc0d7b356a9
title: access-list-a
version: v1
```go
type AccessListMemberSpec struct {
// ...

// MembershipKind describes the kind of membership,
// either "MEMBERSHIP_KIND_USER" or "MEMBERSHIP_KIND_LIST".
MembershipKind string `json:"membership_kind" yaml:"membership_kind"`
}
```

As well as `accesslist.Owner`:

```go
type Owner struct {
// ...

// MembershipKind describes the kind of ownership,
// either "MEMBERSHIP_KIND_USER" or "MEMBERSHIP_KIND_LIST".
MembershipKind string `json:"membership_kind" yaml:"membership_kind"`
}
```

These fields will contain a list of other access lists that will be
included in the access list.
These fields will be used to indicate whether the member/owner refers to
a Teleport user or an Access List.

Two fields will be added to the `AccessList.Status` struct as well:

Access lists included in `dynamic_members.access_list_members` and
`dynamic_members.access_list_owners` will take the membership only
from the list of members in the included access list.
```go
type Status struct {
// ...
OwnerOf []string `json:"owner_of" yaml:"owner_of"`
MemberOf []string `json:"member_of" yaml:"member_of"`
}
```

These fields will be used to store the names (UUIDs) of Access Lists which
the current Access List is an explicit member or owner of, respectively.

# Implementation considerations

## Cycles within lists
## Limitations

The implementation will not support cycles within the hierarchy as
this would introduce confusing options for configuration. Teleport
will return an error if a cycle are introduced. It will also only look
10 layers deep before exiting a lookup to avoid overly complex
hierarchies.
### Cycles

Errors over cycles in the hierarchy will be detected and returned at
access list insertion/update time.
The implementation will not support cycles within the hierarchy, as
this would introduce confusing options for configuration. Teleport
will return an error if self-referential membership or ownership is
detected while modifying an Access List's members or owners.

### Nesting depth

Access list hierarchies will only recurse up to 10 layers deep
initially.
The implementation will not support a hierarchy that is
more than 10 levels deep. An error will be returned if a hierarchy
exceeds this depth while modifying an Access List's members or owners.
This may be configured to a higher value in the future.

## Access list reviews
Errors relating to cycles and depth will also be detected and returned
at Access List insertion time.

Access list periodic reviews will include in the member review page,
the list of nested access lists and an indicator to suggest that its
an access list not an individual member, but not the full list of
users.
## Access List reviews

## Impact on access requests
In the member review page for an Access List review, the list of members
will include both explicit members and nested Access Lists. An indicator
will be included to show that the member is an Access List, not an
individual user.

Access request suggested reviewers will include members included in
the `dynamic_access_lists.access_list_owners` field.
## Impact on Access Requests

The suggested lists field will remain operating as it presently does,
Access Requests' suggested reviewers will include users with inherited
ownership from nested Access Lists.

The Suggested Lists field will remain operating as it presently does,
only showing the list that actually grants the resource.

## Membership and Ownership requires
## Membership and Ownership

A user in a nested access list will only become a member/owner if the
user passes the respective membership/ownership requirements
### Inheritance

## Other considerations
Membership will be inherited when a user is a member in an Access List that
is a member of another Access List.

Ownership will be inherited when a user is a member in an Access List that
is an owner of another Access List.

These rules are recursive - if an Access List is a member of an
Access List that is a member of another Access List, the user will
inherit membership in all three Access Lists (or, ownership, if the
first Access List in the chain is added as an owner).

Access lists will need to be allowed to have empty grants so access
lists can represent only users and permissions can be assigned purely
through membership in other lists.
### Requirements

# Examples
Membership and ownership requirements will be checked at each level of the
hierarchy. If a user does not meet the requirements at a given level,
they will not inherit membership or ownership from that level or any
levels "above" it in the hierarchy.

## Grant inheritance

User Alice is in the below access list which does not include any
other access lists
When calculating a user's login state, the tree of Access Lists will
be traversed, granting roles and traits from each Access List in the
hierarchy that the user has either explicit or inherited membership or
ownership in.

Explicit owners will not inherit roles or traits from any nested
Access Lists they own. They will only be granted roles and traits from
the Access List(s) they are explicit owners of.

## Other considerations

Access lists will need to be allowed to have empty grants so Access
Lists can represent only users, and permissions can be assigned purely
through inclusion in other Access Lists.

# Example

- User Alice is a member in `acl-a`, which does not include any other
Access Lists as members:

```yaml
kind: access_list
Expand All @@ -116,12 +155,12 @@ spec:
roles:
- some-role
traits: {}
title: access-list-a
version: v1
```
- `acl-c` includes members in `acl-a`, grants them `manager`
- `acl-b` includes members in `acl-c`, and grants them `auditor` and `reviewer`
- `acl-c` includes members of `acl-a`, and grants them `manager`
- `acl-b` includes members of `acl-c`, and grants them `auditor` and `reviewer`

```yaml
kind: access_list
Expand All @@ -133,9 +172,9 @@ spec:
- auditor
- reviewer
traits: {}
# list of references to other access lists, for users to include in this access list
dynamic_members:
access_list_members: "acl-c"
# In actuality, members are not stored directly on the Access List resource, this is just for brevity
members:
- acl-c
title: access-list-a
version: v1
---
Expand All @@ -147,24 +186,23 @@ spec:
roles:
- manager
traits: {}
# list of references to other access lists, for users to include in this access list
dynamic_members:
access_list_members: "acl-a"
members:
- acl-a
title: access-list-a
version: v1
```

When calculating a users access roles, the tree of access lists will
be traversed and so upon login, user Alice will have been granted
When calculating a user's access roles, the tree of Access Lists will
be traversed, and so, upon login, user Alice will be granted:

- `some-role` from `acl-a`
- `manager` from `acl-c` as it includes members of `acl-a`
- `auditor` and `reviewer` from `acl-b` as it includes members of
`acl-c`, who also include members of `acl-a`
- `manager` from `acl-c`, as it includes members from `acl-a`
- `auditor` and `reviewer` from `acl-b`, as it includes members from
`acl-c`, which in turn includes members from `acl-a`

# Future considerations

Further development of membership reviews should be considered to
- Further development of membership reviews should be considered to
expand reviews to include members of nested lists and to include
information in the UI that nested may need to be separately reviewed
information in the UI that nested lists may need to be separately reviewed.

0 comments on commit ff91dc0

Please sign in to comment.