diff --git a/.ct.yaml b/.ct.yaml new file mode 100644 index 0000000..952b8b0 --- /dev/null +++ b/.ct.yaml @@ -0,0 +1,3 @@ +helm-extra-args: --timeout 180s +chart-repos: + - stable=https://charts.helm.sh/stable diff --git a/.github/workflows/chart.yml b/.github/workflows/chart.yml new file mode 100644 index 0000000..17c830f --- /dev/null +++ b/.github/workflows/chart.yml @@ -0,0 +1,41 @@ +name: Helm CI + +on: + pull_request: + paths: + - "charts/**" + +permissions: read-all + +jobs: + lint-and-test: + runs-on: ubuntu-20.04 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.9.2 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.7 + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.6.1 + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct --config .ct.yaml list-changed --target-branch ${{ github.event.repository.default_branch }}) + if [[ -n "$changed" ]]; then + echo "changed=true" >> $GITHUB_OUTPUT + fi + - name: Run chart-testing (lint) + run: ct lint --config .ct.yaml --target-branch ${{ github.event.repository.default_branch }} + - name: Create kind cluster + uses: helm/kind-action@v1.10.0 + if: steps.list-changed.outputs.changed == 'true' + - name: Run chart-testing (install) + run: ct install --config .ct.yaml --target-branch ${{ github.event.repository.default_branch }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..5dbbba0 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,88 @@ +name: Release + +on: + push: + tags: + - "v*" + +permissions: read-all + +jobs: + build-and-publish-images: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Login to AWS Public ECR + uses: docker/login-action@v3 + with: + registry: public.ecr.aws + username: ${{ secrets.AWS_ACCESS_KEY_ID }} + password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + - name: Extract tag name + id: extract_tag_name + run: echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT + - name: Build and push clowarden-dbmigrator image + run: | + docker build \ + -f database/migrations/Dockerfile \ + -t public.ecr.aws/g6m3a0y9/clowarden-dbmigrator:${{steps.extract_tag_name.outputs.tag}} \ + -t public.ecr.aws/g6m3a0y9/clowarden-dbmigrator:latest \ + . + docker push --all-tags public.ecr.aws/g6m3a0y9/clowarden-dbmigrator + - name: Build and push clowarden-server image + run: | + docker build \ + -t public.ecr.aws/g6m3a0y9/clowarden-server:${{steps.extract_tag_name.outputs.tag}} \ + -t public.ecr.aws/g6m3a0y9/clowarden-server:latest \ + . + docker push --all-tags public.ecr.aws/g6m3a0y9/clowarden-server + + package-and-publish-helm-chart: + needs: + - build-and-publish-images + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + - name: Install Helm + uses: azure/setup-helm@v4 + - name: Run chart-releaser + run: | + # From: https://github.com/metallb/metallb/blob/293f43c1f78ab1b5fa8879a76746b094bd9dd3ca/.github/workflows/publish.yaml#L134-L163 + # Ref: https://github.com/helm/chart-releaser-action/issues/60 + curl -sSLo cr.tar.gz "https://github.com/helm/chart-releaser/releases/download/v1.6.1/chart-releaser_1.6.1_linux_amd64.tar.gz" + tar -xzf cr.tar.gz + rm -f cr.tar.gz + repo=$(basename "$GITHUB_REPOSITORY") + owner=$(dirname "$GITHUB_REPOSITORY") + tag="${GITHUB_REF_NAME:1}" + exists=$(curl -s -H "Accept: application/vnd.github.v3+json" https://github.com/$GITHUB_REPOSITORY/releases/tag/$repo-chart-$tag -w %{http_code} -o /dev/null) + if [[ $exists != "200" ]]; then + echo "Creating release..." + # package chart + ./cr package charts/$repo + # upload chart to github releases + ./cr upload \ + --owner "$owner" \ + --git-repo "$repo" \ + --release-name-template "{{ .Name }}-chart-{{ .Version }}" \ + --token "${{ secrets.GITHUB_TOKEN }}" + # Update index and push to github pages + ./cr index \ + --owner "$owner" \ + --git-repo "$repo" \ + --index-path index.yaml \ + --release-name-template "{{ .Name }}-chart-{{ .Version }}" \ + --push + else + echo "Release already exists" + fi diff --git a/README.md b/README.md index 5593e2e..ae63204 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ # CLOWarden -**CLOWarden** is a tool that manages the access to resources across multiple services with the initial focus on repositories in a GitHub organization. -CLOWarden allows you to grant access to an individual user or a defined team of users by submitting a PR to a file that defines access rules. +[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/clowarden)](https://artifacthub.io/packages/helm/clowarden/clowarden) -The CNCF initially used [Sheriff](https://github.com/cncf/sheriff) to manage access to resources. CLOWarden has replaced Sheriff with a system that suits better the needs of the CNCF. +**CLOWarden** is a tool that manages access to resources across multiple services, with an initial focus on repositories in a GitHub organization. -CLOWarden supports a legacy configuration mode that allows using [a subset of the Sheriff's permissions configuration file](#configuration) and the [CNCF's people file](https://github.com/cncf/people/blob/main/people.json) to define users, teams and GitHub repositories (the same files currently used by CNCF at ). +The CNCF initially used [Sheriff](https://github.com/cncf/sheriff) to manage access to resources. CLOWarden has replaced Sheriff with a system that suits better the needs of the CNCF. ## How it works @@ -31,9 +30,10 @@ 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 +The first step will be to create a pull request to add the entries below to the configuration files: -(*This configuration intentionally introduces a typo so we can describe CLOWarden's PR validation checks -team1 is misspelled-*): +> [!WARNING] +> This configuration intentionally introduces a typo so we can describe CLOWarden's PR validation checks (team1 is misspelled). ```yaml teams: @@ -76,8 +76,6 @@ Now CLOWarden is happy with the changes proposed! This time, it also tried to he 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. -Outside of the context of a PR it is possible to view an autdit log of the changes made see the [#Audit tool](Audit tool) below - ![valid-config-check-run](docs/screenshots/valid-config-check-run.png) 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: @@ -180,6 +178,8 @@ repositories: visibility: public ``` +### Some tips to avoid problems + It's important to keep in mind that.. - GitHub usernames are case sensitive @@ -189,10 +189,53 @@ It's important to keep in mind that.. - 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 ## Using CLOWarden in your organization -Although has been deployed for use in the CNCF GitHub org, CLOWarden is still in an experimental phase and breaking changes are expected, so we do not recommend its use in other production enviroments yet. Once it stabilizes, we'll publish some additional documentation to make it easier to run your own CLOWarden instance. +You can deploy your own CLOWarden instance by using [the Helm chart provided](https://artifacthub.io/packages/helm/clowarden/clowarden). + +## CLI tool + +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. + +### Building from source + +You can build the CLOWarden CLI tool from the source by using [Cargo](https://rustup.rs), the Rust package manager. + +```text +cargo install --git https://github.com/cncf/clowarden clowarden-cli +``` + +```text +% 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 + +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 +``` ## Contributing diff --git a/charts/clowarden/Chart.yaml b/charts/clowarden/Chart.yaml index 8f7cdde..b013fe0 100644 --- a/charts/clowarden/Chart.yaml +++ b/charts/clowarden/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: clowarden -description: CLOWarden is a tool that automatically manages organizations users, teams and other resources across multiple services +description: CLOWarden is a tool that manages access to resources across multiple services type: application version: 0.1.0 appVersion: 0.1.0 @@ -19,3 +19,18 @@ dependencies: version: 8.2.1 repository: https://charts.helm.sh/stable condition: postgresql.enabled +annotations: + artifacthub.io/category: skip-prediction + artifacthub.io/changes: | + - kind: added + description: Initial release + artifacthub.io/images: | + - name: dbmigrator + image: public.ecr.aws/g6m3a0y9/clowarden-dbmigrator + - name: server + image: public.ecr.aws/g6m3a0y9/clowarden-server + artifacthub.io/links: | + - name: source + url: https://github.com/cncf/clowarden + - name: support + url: https://github.com/cncf/clowarden/issues diff --git a/charts/clowarden/README.md b/charts/clowarden/README.md new file mode 100644 index 0000000..c613553 --- /dev/null +++ b/charts/clowarden/README.md @@ -0,0 +1,104 @@ +# CLOWarden + +[CLOWarden](https://clowarden.io) is a tool that manages access to resources across multiple services. + +## Introduction + +This chart bootstraps a CLOWarden deployment on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +Before installing this chart, you need to [setup a GitHub application](https://docs.github.com/en/apps/creating-github-apps/creating-github-apps/creating-a-github-app). The application requires the following permissions [to be set](https://docs.github.com/en/apps/maintaining-github-apps/editing-a-github-apps-permissions): + +Repository: + +- **Administration**: *read/write* +- **Checks**: *read/write* +- **Contents**: *read* +- **Metadata**: *read* +- **Pull requests**: *read/write* + +Organization: + +- **Administration**: *read/write* +- **Members**: *read/write* + +In addition to those permissions, it must also be subscribed to the following events: + +- *Pull Request* + +CLOWarden expects GitHub events to be sent to the `/webhook/github` endpoint. In the GitHub application, please enable `webhook` and set the target URL to your exposed endpoint (ie: ). You will need to define a random secret for the webhook (you can use the following command to do it: `openssl rand -hex 32`). Please note your webhook secret, as well as the GitHub application ID and private key, as you'll need them in the next step when installing the chart. + +Once your GitHub application is ready you can install it in the organizations you need. + +## Installing the chart + +Create a values file (`my-values.yaml`) that includes the configuration values required for your GitHub application: + +```yaml +server: + githubApp: + # GitHub application ID + appId: 123456 # Replace with your GitHub app ID + + # GitHub application private key + privateKey: |- + -----BEGIN RSA PRIVATE KEY----- + ... + YOUR_APP_PRIVATE_KEY + ... + -----END RSA PRIVATE KEY----- + + # GitHub application webhook secret + webhookSecret: "your-webhook-secret" +``` + +In addition to the GitHub application configuration, you can also add the organizations you'd like to use CLOWarden with at this point: + +```yaml +organizations: + - # Name of the GitHub organization + name: org-name + + # CLOWarden's GitHub application installation id + installationId: 12345678 + + # Repository where the configuration files are located + repository: .clowarden + + # Branch to use in the configuration repository + branch: main + + # Legacy mode configuration + legacy: + # Whether legacy mode is enabled or not (must be at the moment) + enabled: true + + # Path of the Sheriff's permissions file + sheriffPermissionsPath: config.yaml +``` + +CLOWarden includes a CLI tool that can be handy when adding new organizations to your CLOWarden deployment. For more information please see the [repository's README file](https://github.com/cncf/clowarden?#cli-tool). + +To install the chart with the release name `my-clowarden` run: + +```bash +$ helm repo add clowarden https://cncf.github.io/clowarden/ +$ helm install --values my-values.yaml my-clowarden clowarden/clowarden +``` + +The command above deploys CLOWarden on the Kubernetes cluster using the default configuration values and the GitHub application configuration provided. Please see the [chart's default values file](https://github.com/cncf/clowarden/blob/main/charts/clowarden/values.yaml) for a list of all the configurable parameters of the chart and their default values. + +## Uninstalling the chart + +To uninstall the `my-clowarden` deployment run: + +```bash +$ helm uninstall my-clowarden +``` + +This command removes all the Kubernetes components associated with the chart and deletes the release. + +## How CLOWarden works + +For more information about how CLOWarden works from a user's perspective please see the [repository's README file](https://github.com/cncf/clowarden#readme). diff --git a/charts/clowarden/values.yaml b/charts/clowarden/values.yaml index 17788c7..5636fd9 100644 --- a/charts/clowarden/values.yaml +++ b/charts/clowarden/values.yaml @@ -36,7 +36,7 @@ dbmigrator: job: image: # Database migrator image repository (without the tag) - repository: clowarden-dbmigrator + repository: public.ecr.aws/g6m3a0y9/clowarden-dbmigrator # CLOWarden server configuration server: @@ -59,7 +59,7 @@ server: githubApp: # GitHub application ID appId: null - # GitHub application private key path + # GitHub application private key privateKey: null # GitHub application webhook secret webhookSecret: null @@ -79,9 +79,9 @@ server: # Deployment configuration deploy: - replicaCount: 1 + replicaCount: 1 # Do not increase image: - repository: clowarden-server + repository: public.ecr.aws/g6m3a0y9/clowarden-server resources: {} # Services CLOWarden will manage @@ -102,7 +102,7 @@ organizations: # branch: main # # Legacy mode configuration # legacy: - # # Whether legacy mode is enabled or not + # # Whether legacy mode is enabled or not (must be at the moment) # enabled: true # # Path of the Sheriff's permissions file # sheriffPermissionsPath: config.yaml diff --git a/clowarden-cli/src/main.rs b/clowarden-cli/src/main.rs index c9a1069..0f2fafb 100644 --- a/clowarden-cli/src/main.rs +++ b/clowarden-cli/src/main.rs @@ -25,7 +25,7 @@ use std::{env, fs::File, path::PathBuf, sync::Arc}; version, about = "CLOWarden CLI tool -This tool uses the Github API, which requires authentication. Please make sure +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." )] diff --git a/web/public/root_index.html b/web/public/root_index.html index 0ec6406..b00fabd 100644 --- a/web/public/root_index.html +++ b/web/public/root_index.html @@ -154,9 +154,7 @@
- is a tool that automatically manages organizations users, -
- teams and other resources across multiple services + is a tool that manages access to resources across multiple services