{"id":13840695,"url":"https://github.com/cruise-automation/rbacsync","last_synced_at":"2025-04-07T16:17:49.552Z","repository":{"id":41539841,"uuid":"160244024","full_name":"cruise-automation/rbacsync","owner":"cruise-automation","description":"Automatically sync groups into Kubernetes RBAC","archived":false,"fork":false,"pushed_at":"2023-12-18T23:03:38.000Z","size":4592,"stargazers_count":241,"open_issues_count":8,"forks_count":34,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-31T15:18:00.798Z","etag":null,"topics":["go","golang","k8s","kubernetes","kubernetes-controller","kubernetes-operator","kubernetes-rbac"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cruise-automation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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-03T19:40:08.000Z","updated_at":"2025-03-07T00:35:11.000Z","dependencies_parsed_at":"2024-06-18T16:52:06.932Z","dependency_job_id":"aaf557e8-4cd2-47c7-a5d7-d1e95901e0d0","html_url":"https://github.com/cruise-automation/rbacsync","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cruise-automation%2Frbacsync","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cruise-automation%2Frbacsync/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cruise-automation%2Frbacsync/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cruise-automation%2Frbacsync/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cruise-automation","download_url":"https://codeload.github.com/cruise-automation/rbacsync/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247685628,"owners_count":20979085,"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","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":["go","golang","k8s","kubernetes","kubernetes-controller","kubernetes-operator","kubernetes-rbac"],"created_at":"2024-08-04T17:00:52.526Z","updated_at":"2025-04-07T16:17:49.533Z","avatar_url":"https://github.com/cruise-automation.png","language":"Go","funding_links":[],"categories":["Go","Go (531)","Operators vs Controllers"],"sub_categories":["Namespaces"],"readme":"![RBACSync](project/images/logo-horizontal.png)\n\n[![Build Status](https://travis-ci.org/cruise-automation/rbacsync.svg?branch=master)](https://travis-ci.org/cruise-automation/rbacsync)\n\n* [Usage](#usage)\n  + [Custom Resources](#custom-resources)\n    - [Bindings](#bindings)\n    - [Memberships](#memberships)\n  + [Configuration](#configuration)\n    - [Enabling GSuite Group Configuration](#enabling-gsuite-group-configuration)\n  + [Deployment](#deployment)\n* [Development](#development)\n  + [Building](#building)\n  + [Local Development](#local-development)\n* [In Cluster Development](#in-cluster-development)\n* [Release Process](#release-process)\n  + [Tagging your release](#tagging-your-release)\n  + [Pushing your release tag](#pushing-your-release-tag)\n  + [Create your release in Github](#create-your-release-in-github)\n* [License](#license)\n* [Contributions](#contributions)\n\nThis project provides a Kubernetes controller to synchronize RoleBindings and\nClusterRoleBindings, used in [Kubernetes RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/),\nfrom group membership sources using consolidated configuration objects. The\nprovided configuration objects allow you to define \"virtual\" groups that result\nin the creation of RoleBindings and ClusterRoleBindings that directly reference\nall users in the group.\n\nGroup membership can be declared directly in configuration objects or be pulled\nfrom an \"upstream\". Currently, the only supported upstream is GSuite, but we\nmay add others, if required.\n\nUsage\n-----\n\n### Custom Resources\n\nRBACSync leverages [Custom Resource Definitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions)\nto manage binding configuration and group membership declaration. The\nCRDs are available in the [deployment directory](deploy/00-crds.yml). Specific\ninformation about the type declarations are available in the [the source\ncode](pkg/apis/rbacsync/v1alpha/types.go).\n\nThere are two CRDs defined depending on whether you want to create groups with cluster\nscope or namespace scope:\n\n| Custom Resource Definition | Scope      | Description                                              |\n|----------------------------|------------|----------------------------------------------------------|\n| RBACSyncConfig             | Namespaced | Maps groups to users to create namespaced `RoleBindings` |\n| ClusterRBACSyncConfig      | Cluster    | Maps groups to users to create `ClusterRoleBindings`     |\n\nTo define groups with RoleBindings within a namespace, you'll need to create an\nRBACSyncConfig. To define groups that create ClusterRoleBindings, you'll need\nto create ClusterRBACSyncConfig.\n\nThese two configuration objects can be used in concert to correctly configure\nuser bindings to `Roles` and `ClusterRoles` depending on the context.\n\nIf you are confused at any time, it might help to look at the\n[example.yml](example.yml) for details.\n\n#### Bindings\n\nThe configurations used for RBACSync are centered around a `bindings` entry. It\ndeclares a mapping of group name to `RoleBinding` or `ClusterRoleBinding`. We\ncan use a very simple configuration to show this concept:\n\n```yaml\napiVersion: rbacsync.getcruise.com/v1alpha\nkind: ClusterRBACSyncConfig\nmetadata:\n  name: example-simple\nspec:\n  # Defines the roleRef to use against the subjects defined above.\n  bindings:\n  - group: mygroup-admin@getcruise.com\n    roleRef:\n      apiGroup: rbac.authorization.k8s.io\n      kind: ClusterRole\n      name: cluster-admin\n```\n\nThe above is a configuration for the `ClusterRBACSyncConfig` with a single\nbinding entry that will map the Google Group \"mygroup-admin@getcruise.com\". For\neach binding entry, a `ClusterRoleBinding` will be created. It will look\nsimilar to the following:\n\n```yaml\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  annotations:\n    rbacsync.getcruise.com/group: mygroup-admin@getcruise.com\n  labels:\n    owner: example-simple # allows use to select child objects quickly\n  name: example-simple-mygroup-admin@getcruise.com-cluster-admin\n  ownerReferences: # will be owned by the above configuration\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: cluster-admin\nsubjects:\n# Users that are a member of the group, from the upstream\n- apiGroup: rbac.authorization.k8s.io\n  kind: User\n  name: a@getcruise.com\n- apiGroup: rbac.authorization.k8s.io\n  kind: User\n  name: b@getcruise.com\n- apiGroup: rbac.authorization.k8s.io\n  kind: User\n  name: c@getcruise.com\n```\n\nThe above will be created when the configuration is added to the Kubernetes\ncluster. If the upstream group definition changes, updates will be picked up\nafter a configurable polling period. If the configuration that defined this, in\nthis case `example-simple`, is removed, this `ClusterRoleBinding` will be\nautomatically removed.\n\nFor namespace-scoped `RBACSyncConfig`, the behavior is nearly identical except\nfor the following:\n\n1. `RBACSyncConfig` must be defined with a namespace.\n2. All `RoleBindings` created as a result of the `RBACSyncConfig` will be in\n   the same namespace.\n\n`RBACSyncConfig` may reference a `ClusterRole` to grant permissions to\nnamespaced resources defined in the `ClusterRole` within the `RoleBinding`’s\nnamespace. This allows administrators to define a set of common roles for the\nentire cluster, then reuse them within multiple namespaces.\n\nWhen deciding between using the two, you should mostly only need to look at\nwhether your assigning `ClusterRoles` or `Roles` and then use the equivalent\nconfiguration. Refer to the [Kubernetes RBAC documentation](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)\nfor further guidance on that topic.\n\n#### Memberships\n\nGroup memberships allow one to specify the targets of the `RoleBindings` and\n`ClusterRoleBindings` used in a configuration object. Abstractly, we'd like to\nknow based on a group name, what subjects are a member of that group. If you\nare using an upstream, such as GSuite, these memberships are drawn directly\nfrom group memberships define there. There may be cases when you want to store\nthese definitions directly in the cluster or need to augment groups with\nadditional members, such as GCP service accounts.\n\nEach config has a spec which defines `memberships`, calling out each member of\nthe group.  The groups defined in `memberships` may then be referenced in one\nor mores `bindings`.\n\nTo add memberships, simply include a memberships section in the spec,\nmemberships:\n\n```yaml\n  memberships:\n  - group: cluster-admin-group\n    subjects:\n    - kind: User\n      name: a@getcruise.com\n      apiGroup: rbac.authorization.k8s.io\n    - kind: User\n      name: b@getcruise.com\n      apiGroup: rbac.authorization.k8s.io\n    - kind: User\n      name: c@getcruise.com\n  - group: someother-group\n    subjects:\n    - kind: User\n      name: a@getcruise.com\n      apiGroup: rbac.authorization.k8s.io\n```\n\nThe above declares two groups, \"cluster-admin-group\" and \"someother-group\",\neach with a list of subjects. When creating `RoleBindings`, the subjects\ndeclared here will be used as the subjects in the `RoleBinding` object that\ngets created.\n\n\u003e NOTE: If you're using GSuite to configure group memberships, you likely won't\n\u003e need this section. However, it may be useful to add supplementary members or\n\u003e robot accounts to groups using memberships.\n\n### Configuration\n\nFor the most part, you can start using RBACSync with the default deployment,\ndefined in [`deploy/20-deployment.yml`](deploy/20-deployment.yml). This will\nallow you to deploy configurations with bindings and memberships.\n\nFor reference, here are the available flags on the `rbacsync` binary:\n\n```console\nUsage of bin/rbacsync:\n  -alsologtostderr\n\t\tlog to standard error as well as files\n  -debug-addr string\n\t\tbind address for liveness, readiness, debug and metrics (default \":8080\")\n  -gsuite.credentials string\n\t\tpath to service account token json for gsuite access\n  -gsuite.delegator string\n\t\tAccount that has been delegated for use by the service account.\n  -gsuite.enabled\n\t\tenabled membership definitions from gsuite\n  -gsuite.pattern string\n\t\tGroups forwarded to gsuite account must match this pattern\n  -gsuite.timeout duration\n\t\tTimeout for requests to gsuite API (default 30s)\n  -kubeconfig string\n\t\t(optional) absolute path to the kubeconfig file (default \"/home/sday/.kube/config\")\n  -log_backtrace_at value\n\t\twhen logging hits line file:N, emit a stack trace\n  -log_dir string\n\t\tIf non-empty, write log files in this directory\n  -logtostderr\n\t\tlog to standard error instead of files\n  -stderrthreshold value\n\t\tlogs at or above this threshold go to stderr\n  -upstream-poll-period duration\n\t\tpoll period for upstream group updates (default 5m0s)\n  -v value\n\t\tlog level for V logs\n  -version\n\t\tshow the verson and exit\n  -vmodule value\n\t\tcomma-separated list of pattern=N settings for file-filtered logging\n```\n\nIn configuring upstreams, you'll likely have to add one or more flags. Note\nthat you can also increase logging granularity, if you need more in depth\ndebugging.\n\n#### Enabling GSuite Group Configuration\n\nTo use GSuite, you'll need a service account with \"G Suite Domain-Wide\nDelegation of Authority\". It's recommended to read the\n[guide](https://developers.google.com/admin-sdk/directory/v1/guides/delegation)\nto understand how this works in case you run into issues. The blog\n[Navigating the Google Suite Directory\nAPI](https://www.fin.com/post/2017/10/navigating-google-suite-directory-api)\nmay also provide some insight.\n\nThe goal is to end up with two accounts:\n\n1. A \"robot\" GSuite account that acts as a \"delagator\" to the service account.\n2. A \"service account\" in a GCP project that will act as a delegate.\n\nWe then use the credentials of the service account with `rbacsync` to allow it\nto read the GSuite Directory API.\n\n\u003e NOTE: You may be able to get away with delegating to a user account and\n\u003e taking it through the OAuth flow to delegate permissions. It is recommended\n\u003e to have a robot account with restricted permissions to control access and\n\u003e avoid lockouts if a user account experiences problems.\n\nTo setup this account, you'll need to take the following steps:\n\n1. Create a new GSuite account with readonly access to the API on Google\n   Groups. We'll call this the \"robot\" account. It should have the following\n   permissions:\n\n\t- https://www.googleapis.com/auth/admin.directory.group.readonly\n\t- https://www.googleapis.com/auth/admin.directory.group.member.readonly\n\n   Please refer to the GSuite documentation, as the exact process for doing\n   this may have changed.\n2. Create a GCP service account in the GCP project where you're interested in using the GSuite \"robot\" account. Enable [G\n   Suite Domain-wide Delegation](https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority) and note the Client ID.\n3. Using the \"security\" component in the \"admin.google.com\" console, use the\n   Client ID for the service account and add the following scopes, which are\n   the same as those from step 1:\n\t- https://www.googleapis.com/auth/admin.directory.group.member.readonly\n\t- https://www.googleapis.com/auth/admin.directory.group.readonly\n4. Generate the service account credentials. Make sure to save the generated\n   JSON file somewhere safe.\n\nOnce we have the account setup we can modify the deployment to allow `rbacsync`\nto use it. The first step is creating the secret from the service account\ncredentials created in step 5:\n\n```console\nkubectl create secret generic --from-file=token.json=\u003cmy service account credentials path\u003e rbacsync-gsuite-credentials\n```\n\nWe can then apply the following diff to the [`rbacsync` deployment](deploy/20-deployment.yml)\nto use the secret created above:\n\n```diff\n@@ -14,6 +14,10 @@\n     spec:\n       restartPolicy: Always\n       serviceAccountName: rbacsync\n+      volumes:\n+      - name: rbacsync-gsuite-credentials\n+        secret:\n+          secretName: rbacsync-gsuite-credentials\n       containers:\n       - name: rbacsync\n         image: cruise/rbacsync:latest\n@@ -24,6 +28,14 @@\n         - /bin/rbacsync\n         args:\n         - \"-logtostderr\"\n+        - \"-gsuite.enabled\"\n+        - \"-gsuite.credentials\"\n+        - \"/run/secrets/gsuite/token.json\"\n+        - \"-gsuite.delegator\"\n+        - \"my-rbacsync-robot@getcruise.com\"\n+        volumeMounts:\n+        - mountPath: /run/secrets/gsuite\n+          name: rbacsync-gsuite-credentials\n         imagePullPolicy: Always\n         ports:\n         - name: debug-port\n```\n\nIn the above, we set several flags to pass to `rbacsync`:\n\n- `-gsuite.enabled`: enables the GSuite upstream for groups.\n- `-gsuite.credentials`: path to the credentials generated for the service\n  account. We map them to the secret volume mount location above.\n- `-gsuite.delegator`: This is the delegator whom the service account acts on\n  behalf of. We call this the \"robot\" account in the instructions above. Be\n  sure to set the argument to whatever account you use.\n\n\u003e NOTE: You can also use `-gsuite.pattern` to limit which group names are sent\n\u003e upstream for queries. That takes a regular expression that must be matched\n\u003e before it will be allowed to query the upstream.\n\nOnce the above is configured and deployed, groups referenced in `bindings` will\nbe automatically queried against GSuite. If `memberships` have the same name as\nan upstream group, the subject lists from the upstream and the `memberships`\nsection will be merged.\n\n### Deployment\n\n\u003e WARNING: Before running any commands here, make sure you are in the right\n\u003e cluster context. This will deploy to whatever cluster kubectl is currently\n\u003e configured for.\n\nYou can deploy the rbacsync with the following command:\n\n\tkubectl apply -f deploy/\n\nOnce it has been deployed, you'll need to push a config to specify group\nmembers using the [CRDs](deploy/00-crds.yml) defined in this project. There are\ntwo CRDs defined depending on whether you want to create groups with cluster\nscope or namespace scope. To define groups with RoleBindings within a\nnamespace, you'll need to create an RBACSyncConfig. To define groups that\ncreate ClusterRoleBindings, you'll need to create ClusterRBACSyncConfig.\n\nIf the RBACSyncConfig changes, the associated RoleBindings will be updated to\nreflect the difference. For example, if new group members are added, the\nRoleBinding will be updated with the new subjects.\n\nIf you remove RBACSyncConfig or ClusterRBACSyncConfig, any associated\nRoleBindings or ClusterRoleBindings will be removed, as well.\n\nDevelopment\n-----------\n\n### Building\n\nBuilding is easy to do. Make sure to setup your local environment according to\nhttps://golang.org/doc/code.html. Once setup, you should be able to build the\nbinaries using the following command:\n\n```\nmake\n```\n\nGenerated binaries will then be available in `bin/`. See the section on local\ndevelopment for how to use the binary.\n\n### Local Development\n\nFor developing on rbacsync, you can run inside or outside the cluster. For\nchanges with lots of iteration, it is probably best to run it locally, since\nbuilding and pushing an image to a deployment can be time consuming. The\nprocess would use the following commands:\n\n\u003e WARNING: Before running any commands here, make sure you are in the right\n\u003e cluster context. This will deploy to whatever cluster kubectl is currently\n\u003e configured for.\n\n```\nkubectl apply -f deploy/10-deployment.yml\nmake\nbin/rbacsync -logtostderr\n```\n\nThe above will use your local kube context to run rbacsync, so you'll need\n`cluster-admin` Role for this to work. rbacsync will fire log messages and\nevents complaining about permissions if it cannot create the specified roles.\n\nWhen you run the process, nothing will happen unless it has CRs to operate one.\nYou can use the [example.yml](example.yml) to try it out:\n\n```\nkubectl apply -f example.yml\n```\n\nYou'll know its working if you see log messages indicating that it saw the\nconfigs.\n\nIn Cluster Development\n----------------------\n\nIf you are working on changes that require rbacsync to be running in a cluster,\nsuch as when checking whether operations will work correctly, you can use the\n`deploy` target.  To test in a cluster, the following can be run:\n\n\tmake REGISTRY=cruise/ deploy\n\nThe above will build the image, push it to a registry, apply the CRDs\nand deployment to the kubernetes context and update the deployment to\nuse the created image. This makes iterating on testing within a cluster\nmuch easier.\n\nYou'll need cluster admin to perform this operation.\n\nRelease Process\n---------------\n\nRBACSync is versioned using [semantic versioning](https://semver.org/). For the\nmost part, patch releases should be only bug fixes, minor releases can have\nbackwards compatible feature introductions and major releases are for breaking\nchanges. If you can't decide whether a feature or change is breaking, err on\nthe side of caution when incrementing the version number and just do it.\n\nThe release process for rbacsync is triggered with tags. Every build in master\nwill pickup the tag and create a version number relative, using a git\ncommitish, to the tag and push it to the registry. For production, you should\nonly use exact tags, and, if possible, only proper releases, meaning no release\ncandidates, alphas or betas.\n\n### Tagging your release\n\nTo perform a release, you simply need to push a tag to the repository. To\ncreate a tag, run the following, with the new version number of course:\n\n```\ngit tag -s v0.1.0\n```\n\nNotice that the version number is _always_ prefixed with a `v` when it appears\nas a tag. This allows us to easily identify version tags with a text prefix. We\nalso sign the tag with a PGP key. If you haven't already done so, it is\nrecommended to generate a PGP key for your workstation and add it to github.\nWhen you run this command, an editor will pop up to include a release message.\nThe following format is usually sufficient:\n\n```\nrbacsync 0.1.0\n\nWith this release, we introduce support for Google Groups API with\nGSuite Directory SDK. This allows one to configure groups without\ndeclared memberships that are queried to the GSuite upstream resource.\n```\n\nThere may be releases with complex information for upgrades and caveats, so\nfeel free to be verbose. Once you are ready, save in the editor and the tag\nwill be created. To push it to github, run the following command:\n\n### Pushing your release tag\n\n```\ngit push --tags origin v0.1.0\n```\n\nThis will push the tag remotely, and start the build and push for rbacsync.\nMake sure to check in CircleCI to ensure it was triggered.\n\n### Create your release in Github\n\nIn addition to pushing this tag, it is also recommended to create a release in\nthe [releases page](https://github.com/cruise-automation/rbacsync/releases). Make\nsure to name it consistently with other releases. It should be sufficient to\nuse the exact same text from the tag, but you may have to tweak the formatting\nto be compatible with markdown.\n\nWhile this is an extra step when releasing the software, it is very helpful\nwhen looking at a project to see its releases properly documented in github.\nAlso follow this practice to have a healthy project!\n\n# License\n\nCopyright 2018 Cruise LLC\n\nLicensed under the [Apache License Version 2.0](LICENSE) (the \"License\");\nyou may not use this project except in compliance with the License.\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\n# Contributions\n\nContributions are welcome! Please see the agreement for contributions in\n[CONTRIBUTING.md](CONTRIBUTING.md).\n\nCommits must be made with a Sign-off (`git commit -s`) certifying that you\nagree to the provisions in [CONTRIBUTING.md](CONTRIBUTING.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcruise-automation%2Frbacsync","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcruise-automation%2Frbacsync","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcruise-automation%2Frbacsync/lists"}