{"id":20290635,"url":"https://github.com/gocardless/theatre","last_synced_at":"2025-08-21T02:31:11.384Z","repository":{"id":34146567,"uuid":"162610911","full_name":"gocardless/theatre","owner":"gocardless","description":"GoCardless' collection of Kubernetes extensions","archived":false,"fork":false,"pushed_at":"2025-08-11T18:53:25.000Z","size":25125,"stargazers_count":23,"open_issues_count":13,"forks_count":17,"subscribers_count":57,"default_branch":"master","last_synced_at":"2025-08-14T09:53:59.723Z","etag":null,"topics":["kubernetes","kubernetes-operators"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gocardless.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-20T17:28:50.000Z","updated_at":"2025-03-24T16:49:15.000Z","dependencies_parsed_at":"2024-02-05T16:52:53.054Z","dependency_job_id":"39d0d957-00ff-4023-9a3d-516c949d87ec","html_url":"https://github.com/gocardless/theatre","commit_stats":{"total_commits":495,"total_committers":22,"mean_commits":22.5,"dds":0.7393939393939394,"last_synced_commit":"c94dd8f879fd2a2ffbea6275620cb15b4ad061e6"},"previous_names":["lawrencejones/rbac-directory"],"tags_count":40,"template":false,"template_full_name":null,"purl":"pkg:github/gocardless/theatre","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Ftheatre","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Ftheatre/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Ftheatre/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Ftheatre/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gocardless","download_url":"https://codeload.github.com/gocardless/theatre/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gocardless%2Ftheatre/sbom","scorecard":{"id":433132,"data":{"date":"2025-08-11","repo":{"name":"github.com/gocardless/theatre","commit":"c630a3b0fc5265a868ada8fcdf1e8aeeb4bfae1a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.1,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/build-integration.yml:1","Warn: topLevel 'contents' permission set to 'write': .github/workflows/release.yml:20","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:44: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:56: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:70: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build-integration.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/build-integration.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:61: update your workflow using https://app.stepsecurity.io/secureworkflow/gocardless/theatre/release.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:2","Warn: containerImage not pinned by hash: Dockerfile:12: pin your Docker image by updating ubuntu:jammy-20230522 to ubuntu:jammy-20230522@sha256:ac58ff7fe25edc58bdf0067ca99df00014dbd032e2246d30a722fa348fd799a5","Warn: npmCommand not pinned by hash: .github/workflows/build-integration.yml:37","Info:   0 out of  12 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: github.com/gocardless/.github/SECURITY.md:1","Info: Found linked content: github.com/gocardless/.github/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: github.com/gocardless/.github/SECURITY.md:1","Info: Found text in security policy: github.com/gocardless/.github/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v4.3.0 not signed: https://api.github.com/repos/gocardless/theatre/releases/204748087","Warn: release artifact v4.2.3 not signed: https://api.github.com/repos/gocardless/theatre/releases/139949486","Warn: release artifact v4.2.2 not signed: https://api.github.com/repos/gocardless/theatre/releases/109925616","Warn: release artifact v4.2.1 not signed: https://api.github.com/repos/gocardless/theatre/releases/109182257","Warn: release artifact v4.2.0 not signed: https://api.github.com/repos/gocardless/theatre/releases/108848370","Warn: release artifact v4.3.0 does not have provenance: https://api.github.com/repos/gocardless/theatre/releases/204748087","Warn: release artifact v4.2.3 does not have provenance: https://api.github.com/repos/gocardless/theatre/releases/139949486","Warn: release artifact v4.2.2 does not have provenance: https://api.github.com/repos/gocardless/theatre/releases/109925616","Warn: release artifact v4.2.1 does not have provenance: https://api.github.com/repos/gocardless/theatre/releases/109182257","Warn: release artifact v4.2.0 does not have provenance: https://api.github.com/repos/gocardless/theatre/releases/108848370"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/release.yml:45"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw","Warn: Project is vulnerable to: GO-2024-2631 / GHSA-c5q2-7r4c-mv6g"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T03:51:42.380Z","repository_id":34146567,"created_at":"2025-08-19T03:51:42.380Z","updated_at":"2025-08-19T03:51:42.380Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271416760,"owners_count":24755948,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-21T02:00:08.990Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kubernetes","kubernetes-operators"],"created_at":"2024-11-14T15:08:34.147Z","updated_at":"2025-08-21T02:31:11.042Z","avatar_url":"https://github.com/gocardless.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Theatre\n\nThis project contains GoCardless' Kubernetes extensions, in the form of\noperators, admission controller webhooks and associated CLIs. The aim of this\nproject is to provide a space to write Kubernetes extensions where:\n\n1. Doing the right thing is easy; it is difficult to make mistakes!\n2. Each category of Kubernetes extension has a well defined implementation pattern\n3. Writing meaningful tests is easy, with minimal boilerplate\n\n## API Groups\n\nTheatre provides various extensions to vanilla Kubernetes. These extensions are\ngrouped under separate API groups, all of which exist under the\n`*.crd.gocardless.com` namespace.\n\n### RBAC\n\nUtilities to extend the default Kubernetes role-based access control (RBAC)\nresources.\nThese CRDs are motivated by real-world use cases when using\nKubernetes with an organisation that uses GSuite, and which frequently onboards\nnew developers.\n\n- [`DirectoryRoleBinding`][sample-drb] is a resource that provisions standard\n  `RoleBinding`s, which contain the subjects defined in a  Google group.\n\n\u003e Note: In a GKE Kubernetes cluster this may soon be superseded by the [Google\n\u003e Groups for GKE][gke-groups] functionality.\n\n[sample-drb]: config/samples/rbac_v1alpha1_directoryrolebinding.yaml\n[gke-groups]: https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#google-groups-for-gke\n\n### Workloads\n\nExtends core workload resources with new CRDs. Extensions within this group can be\nexpected to create or mutate pods, deployments, etc.\n\n- [Consoles](controllers/workloads/console/README.md): Provide engineers with a temporary\n  dedicated pod to perform operational tasks, avoiding the need to provide\n  `pods/exec` permissions on production workloads.\n\n### [Vault](apis/vault/v1alpha1/README.md)\n\nUtilities for interacting with Vault. Primarily used to inject secret material\ninto pods by use of annotations.\n\n- `secrets-injector.vault.crd.gocardless.com` webhook for injecting the\n  `theatre-secrets` tool to populate a container's environment with secrets\n  from Vault before executing.\n\n## Command line interfaces\n\nAs well as Kubernetes controllers this project also contains supporting CLI\nutilities.\n\n### theatre-consoles\n\n`theatre-consoles` is a suite of commands that provides the ability to create,\nlist, attach to and authorise [consoles](#workloads).\n\nRun: `go run cmd/theatre-consoles/main.go`\n\n### theatre-secrets\n\nSee the [command README](cmd/theatre-secrets/README.md) for further details.\n\nRun: `go run cmd/theatre-secrets/main.go`\n\n## Getting Started\n\nTheatre assumes developers have several tools installed to provide development\nand testing capabilities. The following will configure a macOS environment with\nall the necessary dependencies:\n\n\n```shell\nmake install-tools-homebrew\nmake install-tools-kubebuilder\nmake install-tools\nsudo mkdir /usr/local/kubebuilder\ncurl -fsL \"https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.1/kubebuilder_2.3.1_$(go env GOOS)_$(go env GOARCH).tar.gz\" | \\\n  sudo tar -xvz --strip=1 -C /usr/local/kubebuilder\nexport KUBEBUILDER_ASSETS=/usr/local/kubebuilder/bin\n```\n\n## Local development environment\n\nFor developing changes, you can make use of the acceptance testing\ninfrastructure to install the code into a local Kubernetes-in-Docker\n([Kind][kind]) cluster.\nEnsure `kind` is installed (as per the [getting started\nsteps][#getting-started]) and then run the following:\n\n```shell\nmake build\nmake test\nmake acceptance-e2e\n```\n\nYou can also run the individual commands, check the Makefile for more details,\n\nExample: get the kind cluster read for the acceptance tests\n\n```shell\ngo run cmd/acceptance/main.go prepare # prepare the cluster, install theatre\n```\n\nAt this point a development cluster has been provisioned. Your current local\nKubernetes context will have been changed to point to the test cluster. You\nshould see the following if you inspect kubernetes:\n\n```console\n$ kubectl get pods --all-namespaces | grep -v kube-system\nNAMESPACE        NAME                                        READY   STATUS    RESTARTS   AGE\ntheatre-system   theatre-rbac-manager-0                      1/1     Running   0          5m\ntheatre-system   theatre-vault-manager-0                     1/1     Running   0          5m\ntheatre-system   theatre-workloads-manager-0                 1/1     Running   0          5m\nvault            vault-0                                     1/1     Running   0          5m\n```\n\nAll of the controllers and webhooks, built from the local working copy of the\ncode, have been installed into the cluster.\n\nAs this is a fully-fledged Kubernetes cluster, at this point you are able to\ninteract with it as you would with any other cluster, but also have the ability\nto use the custom resources defined in theatre, e.g. creating a `Console`.\n\nIf changes are made to the code, then you must re-run the `prepare` step in\norder to update the cluster with images built from the new binaries.\n\n[kind]: https://github.com/kubernetes-sigs/kind\n\n## Tests\n\nTheatre has test suites at several different levels, each of which play a\nspecific role. All of these suites are written using the [Ginkgo][ginkgo]\nframework.\n\nIn order to setup your local testing environment for unit and integration tests do the following:\n\n```shell\n$ make install-tools\n$ # install setup-envtest which configures etcd and kube-apiserver binaries for envtest\n$ # https://book.kubebuilder.io/reference/envtest.html#configuring-envtest-for-integration-tests\n$ # https://github.com/kubernetes-sigs/controller-runtime/tree/master/tools/setup-envtest#envtest-binaries-manager\n$ # Configures envtest to use k8s 1.24.x binaries, in your shell (if required)\n$ eval $(setup-envtest use -i -p env 1.24.x)\n```\n\n- **Unit**: Standard unit tests, used to exhaustively specify the functionality of\n  functions or objects.\n\n  Invoked with the `ginkgo` CLI. (requires setup-envtest variable)\n\n```\nmake test\n```\n\n  [Example unit test](apis/workloads/v1alpha1/helpers_test.go).\n\n- **Integration**: Integration tests run the custom controller code and\n  integrates this with a temporary Kubernetes API server, therefore providing an\n  environment where the Kubernetes API can be used to manipulate custom objects.\n\n  This environment has no Kubernetes nodes, and does not run any other\n  controllers such as `kube-controller-manager`, therefore it will not run pods.\n\n  These suites provide a good balance between runtime and realism, and are\n  therefore useful for rapid iteration when developing changes.\n\n  Invoked with the `ginkgo` CLI.\n\n  [Example integration test](apis/workloads/v1alpha1/integration/priority_integration_test.go).\n\n- **Acceptance**: Acceptance is used for full end-to-end (E2E) tests,\n  provisioning a fully functional Kubernetes cluster with all custom controllers\n  and webhooks installed.\n\n  The acceptance tests are much slower to set up, and so are typically used\n  sparingly compared to the other suites, but provide essential validation in CI\n  and at the end of development cycles that the code correctly interacts with\n  the other components of a Kubernetes cluster.\n\n  Invoked with: `make acceptance-run`\n\n  [Example acceptance test](cmd/workloads-manager/acceptance/acceptance.go).\n\n[ginkgo]: https://onsi.github.io/ginkgo\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgocardless%2Ftheatre","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgocardless%2Ftheatre","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgocardless%2Ftheatre/lists"}