CLOWarden is a tool that manages access to resources across multiple services, with an initial focus on repositories in a GitHub organization.
The CNCF initially used Sheriff to manage access to resources. CLOWarden has replaced Sheriff with a system that suits better the needs of the CNCF.
CLOWarden's main goal is to ensure that the resources' desired state, as defined in the configuration files, matches the actual state in the corresponding services. This is achieved by running reconciliation jobs, that can be triggered on-demand or periodically. These reconciliation jobs are in charge of applying the necessary changes to address the differences between the desired and actual state on each service, which is done by delegating some work on specialized service handlers.
CLOWarden monitors pull requests created in the configuration repository and, when applicable, it validates the proposed changes to access rules and creates reconciliation jobs to apply the necessary changes. This is what we call an on-demand reconciliation job: it's created as a result of a user's submitted pull request, and changes are applied immediately once the pull request is approved and merged.
Sometimes, however, this may not be enough. Changes can be applied manually to the service bypassing the configuration files (i.e. from the GitHub settings UI), and CLOWarden still needs to make sure that the actual state matches the desired state documented in the configuration files. So in addition to on-demand reconciliation jobs, CLOWarden runs periodic ones to ensure everything is all right all the time.
Warning
Please note that during the reconciliation process, in an attemtp to keep the actual state in sync with the desired state, CLOWarden will remove resources that are not defined in the configuration file (i.e. teams and permissions, but not repositories). Always make sure that the configuration file represents the actual state (or that you are OK with the changes that will be applied) before enabling the service. The generate
subcommand of the CLI tool can be helpful to create an initial configuration file from the actual state, whereas the diff
subcommand can be used to display the differences between the actual and desired state (i.e. what changes will be applied when the service is enabled based on the current configuration file).
The core piece of state in CLOWarden is the directory, which is a catalog that contains teams and users. The directory is at the disposal of all the services handlers, allowing them to take the appropriate action for each directory change detected. For example, when a new team is added to the directory, the GitHub service handler will create that team on the GitHub organization.
But teams and users may not be enough in some cases, and some service handlers may need to define additional resources. This is the case of the GitHub service handler, which defines an additional resource, the repository.
Changes to resources in services managed by CLOWarden should be proposed via pull requests. CLOWarden will check all pull requests created in the configuration repository defined and, when it detects that the PR contains changes to any of the configuration files, it will start working on it.
Let's go through a full example to see how this would work in practice.
Our goal in this example will be to create a new team (named team1
) with one maintainer and one member, as well as a new repository (named repo1
). We want to give team1
write permissions on repo1
, and we'd also like to add a external collaborator, named collaborator1
, with read permissions.
The first step will be to create a pull request to add the entries below to the configuration files:
Warning
This configuration intentionally introduces a typo so we can describe CLOWarden's PR validation checks (team1 is misspelled).
teams:
- name: tem1 # This is a deliberate typo. The value should be "team1" not "tem1"
maintainers:
- maintainer1
members:
- member1
...
repositories:
- name: repo1
teams:
team1: write # team1 does not exist! The CLOWarden validation check will report an error in a PR as a comment
external_collaborators:
collaborator1: read
visibility: public
As soon as the pull request is created, CLOWarden validates the changes proposed.
One of the goals of CLOWarden is to make it as simple as possible for maintainers to review and approve suggested changes to the configuration. To do that, CLOWarden provides feedback in pull requests in the form of comments. Suggested changes can be invalid for a number of reasons, like a syntax problem in the configuration file, or not following any of the rules, like using an invalid role when defining permissions. CLOWarden tries its best to give helpful feedback to the pull request creator, to point them in the right direction and help address errors without requiring the maintainers intervention.
In this case, the error we introduced intentionally was caught: we incorrectly defined the new team as tem1
, but then try to reference it as team1
in the repository access definition.
If this error had not been caught at validation time, a team named tem1
would have been created and the process of granting permissions to team1
on repo1
would have failed as team1
wouldn't have existed.
Please note that, in addition to the feedback comment, CLOWarden created a check in the PR to indicate that the configuration changes are not valid. When used in combination with branch protection, this can help prevent that invalid configuration changes are merged.
The pull request creator can now push a fix to address these issues. Once that's done, CLOWarden will validate the changes again automatically.
Now CLOWarden is happy with the changes proposed! This time, it also tried to help the maintainer who will approve the changes by describing in the comment what had changed.
Sometimes this may be easy to spot by just looking at a the diff on the PR. But on other occasions, depending on the changes applied, it can get trickier and be error prone, as just a single extra space or tabulation can have unintented consequences. So CLOWarden simplifies this by analyzing the changes itself and displaying them in an easy to read way as a comment on the PR.
Now that the changes are valid, the check has been updated to reflect the new status and the PR can be merged safely once the maintainers are ready. As soon as this happens, CLOWarden will create a reconciliation job and will apply the necessary changes so that the actual state in the services matches the new desired state defined in the configuration. Once the job is executed, a new comment will be posted on the PR with more details:
In this case all changes were applied successfully, but if something would have gone wrong the comment would display the corresponding error.
CLOWarden registers all changes applied to the services in a database. Even though most of the time all information related to a given change will be accessible on the PR that triggered it, sometimes it may be necessary to go a bit further to answer questions like:
- When was user1 granted access to repository1 and who approved granting that access?
- In what PR was team1 removed?
- What changes have been applied by automatic periodic reconciliations during the last 24 hours?
To help to answer these questions quickly, CLOWarden provides an audit tool that allows maintainers to easily search and inspect applied changes. The audit tool can be accessed by using a web browser and is available at: https://YOUR-CLOWARDEN-URL/audit/
.
The following services are supported at the moment:
Operations supported:
- Add teams
- Remove teams
- Add maintainers or members to teams
- Remove maintainers or members from teams
- Add repositories
- Add teams to repositories
- Remove teams from repositories
- Update teams' role in repository
- Add collaborators to repositories
- Remove collaborators from repositories
- Update collaborators' role in repository
- Update repository visibility
CLOWarden supports a legacy configuration mode that allows using a subset of the Sheriff's permissions configuration file.
teams:
- name: <github_team_slug>
# Team maintainers
#
# - Values must be valid GitHub usernames (case sensitive)
# - At least one team maintainer must be specified
# - Maintainers must already be members of the organization
# - Can be omitted if at least one maintainer is defined via formation
maintainers:
- <github_username>
- <github_username>
# Team members
#
# - Values must be valid GitHub usernames (case sensitive)
members:
- <github_username>
- <github_username>
# Formation allows populating teams' maintainers and members from the
# content of other teams
#
# - Each value must be a valid GitHub team slug
# - Formation is not recursive
# - This field can be used in combination with maintainers and members
formation:
- <github_team_slug>
- <github_team_slug>
repositories:
- name: <github_repository_name>
# Teams with access to the repository.
# See https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/repository-roles-for-an-organization
#
# - Key: GitHub team slug
# - Value: access level
# - Value options: read | triage | write | maintain | admin
teams:
<github_team_slug>: maintain
<github_team_slug>: write
# External collaborators with access to the repository
# See https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/repository-roles-for-an-organization
#
# - Key: GitHub username (case sensitive)
# - Value: access level
# - Value options: read | triage | write | maintain | admin
external_collaborators:
<github_username>: write
<github_username>: read
# Repository visibility
#
# - Value options: public | private | internal
# - Default: public
visibility: public
It's important to keep in mind that..
- GitHub usernames are case sensitive
- Repositories and team names must contain only lowercase letters, numbers or hyphens (in the case of teams, the GitHub team slug must be used)
- Teams maintainers must belong to the organization before being added to the teams
- Teams maintainers and members fields can be omitted when the field formation is defined and one of the subteams has at least one maintainer
- It is possible to use the formation field in teams and at the same time explicitly define some team maintainers and members
- Teams formation is not recursive. If a subteam is also using formation, its subteams will be ignored
- GitHub repositories permissions granted using teams won't be effective until the team member has accepted the invitation to the organization
- Before renaming a GitHub username, make sure it's not used as a team maintainer in the configuration file
You can deploy your own CLOWarden instance by using the Helm chart provided.
CLOWarden includes a CLI tool that can be handy when adding new organizations to your CLOWarden deployment.
You can use it to:
- Validate the configuration in the repository provided
- Display changes between the actual state and the desired state
- Generate a configuration file from the actual state
Note
This tool uses the GitHub API, which requires authentication. Please make sure you provide a GitHub token (with repo and read:org scopes) by setting the GITHUB_TOKEN environment variable.
You can build the CLOWarden CLI tool from the source by using Cargo, the Rust package manager.
cargo install --git https://github.com/cncf/clowarden clowarden-cli
% clowarden-cli --help
CLOWarden CLI tool
This tool uses the GitHub API, which requires authentication. Please make sure
you provide a GitHub token (with repo and read:org scopes) by setting the
GITHUB_TOKEN environment variable.
Usage: clowarden-cli <COMMAND>
Commands:
diff Display changes between the actual state (as defined in the services) and the desired state (as defined in the configuration)
generate Generate configuration file from the actual state (experimental)
validate Validate the configuration in the repository provided
help Print this message or the help of the given subcommand(s)
Options:
-h, --help Print help
-V, --version Print version
Please see CONTRIBUTING.md for more details.
This project follows the CNCF Code of Conduct.
CLOWarden is an Open Source project licensed under the Apache License 2.0.