MCPcopy Index your code
hub / github.com/cruise-automation/rbacsync

github.com/cruise-automation/rbacsync @v1.3.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.3.0 ↗ · + Follow
299 symbols 888 edges 47 files 173 documented · 58%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

RBACSync

Build Status

This project provides a Kubernetes controller to synchronize RoleBindings and ClusterRoleBindings, used in Kubernetes RBAC, from group membership sources using consolidated configuration objects. The provided configuration objects allow you to define "virtual" groups that result in the creation of RoleBindings and ClusterRoleBindings that directly reference all users in the group.

Group membership can be declared directly in configuration objects or be pulled from an "upstream". Currently, the only supported upstream is GSuite, but we may add others, if required.

Usage

Custom Resources

RBACSync leverages Custom Resource Definitions to manage binding configuration and group membership declaration. The CRDs are available in the deployment directory. Specific information about the type declarations are available in the the source code.

There are two CRDs defined depending on whether you want to create groups with cluster scope or namespace scope:

Custom Resource Definition Scope Description
RBACSyncConfig Namespaced Maps groups to users to create namespaced RoleBindings
ClusterRBACSyncConfig Cluster Maps groups to users to create ClusterRoleBindings

To define groups with RoleBindings within a namespace, you'll need to create an RBACSyncConfig. To define groups that create ClusterRoleBindings, you'll need to create ClusterRBACSyncConfig.

These two configuration objects can be used in concert to correctly configure user bindings to Roles and ClusterRoles depending on the context.

If you are confused at any time, it might help to look at the example.yml for details.

Bindings

The configurations used for RBACSync are centered around a bindings entry. It declares a mapping of group name to RoleBinding or ClusterRoleBinding. We can use a very simple configuration to show this concept:

apiVersion: rbacsync.getcruise.com/v1alpha
kind: ClusterRBACSyncConfig
metadata:
  name: example-simple
spec:
  # Defines the roleRef to use against the subjects defined above.
  bindings:
  - group: mygroup-admin@getcruise.com
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: cluster-admin

The above is a configuration for the ClusterRBACSyncConfig with a single binding entry that will map the Google Group "mygroup-admin@getcruise.com". For each binding entry, a ClusterRoleBinding will be created. It will look similar to the following:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbacsync.getcruise.com/group: mygroup-admin@getcruise.com
  labels:
    owner: example-simple # allows use to select child objects quickly
  name: example-simple-mygroup-admin@getcruise.com-cluster-admin
  ownerReferences: # will be owned by the above configuration
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
# Users that are a member of the group, from the upstream
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: a@getcruise.com
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: b@getcruise.com
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: c@getcruise.com

The above will be created when the configuration is added to the Kubernetes cluster. If the upstream group definition changes, updates will be picked up after a configurable polling period. If the configuration that defined this, in this case example-simple, is removed, this ClusterRoleBinding will be automatically removed.

For namespace-scoped RBACSyncConfig, the behavior is nearly identical except for the following:

  1. RBACSyncConfig must be defined with a namespace.
  2. All RoleBindings created as a result of the RBACSyncConfig will be in the same namespace.

RBACSyncConfig may reference a ClusterRole to grant permissions to namespaced resources defined in the ClusterRole within the RoleBinding’s namespace. This allows administrators to define a set of common roles for the entire cluster, then reuse them within multiple namespaces.

When deciding between using the two, you should mostly only need to look at whether your assigning ClusterRoles or Roles and then use the equivalent configuration. Refer to the Kubernetes RBAC documentation for further guidance on that topic.

Memberships

Group memberships allow one to specify the targets of the RoleBindings and ClusterRoleBindings used in a configuration object. Abstractly, we'd like to know based on a group name, what subjects are a member of that group. If you are using an upstream, such as GSuite, these memberships are drawn directly from group memberships define there. There may be cases when you want to store these definitions directly in the cluster or need to augment groups with additional members, such as GCP service accounts.

Each config has a spec which defines memberships, calling out each member of the group. The groups defined in memberships may then be referenced in one or mores bindings.

To add memberships, simply include a memberships section in the spec, memberships:

  memberships:
  - group: cluster-admin-group
    subjects:
    - kind: User
      name: a@getcruise.com
      apiGroup: rbac.authorization.k8s.io
    - kind: User
      name: b@getcruise.com
      apiGroup: rbac.authorization.k8s.io
    - kind: User
      name: c@getcruise.com
  - group: someother-group
    subjects:
    - kind: User
      name: a@getcruise.com
      apiGroup: rbac.authorization.k8s.io

The above declares two groups, "cluster-admin-group" and "someother-group", each with a list of subjects. When creating RoleBindings, the subjects declared here will be used as the subjects in the RoleBinding object that gets created.

NOTE: If you're using GSuite to configure group memberships, you likely won't need this section. However, it may be useful to add supplementary members or robot accounts to groups using memberships.

Configuration

For the most part, you can start using RBACSync with the default deployment, defined in deploy/20-deployment.yml. This will allow you to deploy configurations with bindings and memberships.

For reference, here are the available flags on the rbacsync binary:

Usage of bin/rbacsync:
  -alsologtostderr
        log to standard error as well as files
  -debug-addr string
        bind address for liveness, readiness, debug and metrics (default ":8080")
  -gsuite.credentials string
        path to service account token json for gsuite access
  -gsuite.delegator string
        Account that has been delegated for use by the service account.
  -gsuite.enabled
        enabled membership definitions from gsuite
  -gsuite.pattern string
        Groups forwarded to gsuite account must match this pattern
  -gsuite.timeout duration
        Timeout for requests to gsuite API (default 30s)
  -kubeconfig string
        (optional) absolute path to the kubeconfig file (default "/home/sday/.kube/config")
  -log_backtrace_at value
        when logging hits line file:N, emit a stack trace
  -log_dir string
        If non-empty, write log files in this directory
  -logtostderr
        log to standard error instead of files
  -stderrthreshold value
        logs at or above this threshold go to stderr
  -upstream-poll-period duration
        poll period for upstream group updates (default 5m0s)
  -v value
        log level for V logs
  -version
        show the verson and exit
  -vmodule value
        comma-separated list of pattern=N settings for file-filtered logging

In configuring upstreams, you'll likely have to add one or more flags. Note that you can also increase logging granularity, if you need more in depth debugging.

Enabling GSuite Group Configuration

To use GSuite, you'll need a service account with "G Suite Domain-Wide Delegation of Authority". It's recommended to read the guide to understand how this works in case you run into issues. The blog Navigating the Google Suite Directory API may also provide some insight.

The goal is to end up with two accounts:

  1. A "robot" GSuite account that acts as a "delagator" to the service account.
  2. A "service account" in a GCP project that will act as a delegate.

We then use the credentials of the service account with rbacsync to allow it to read the GSuite Directory API.

NOTE: You may be able to get away with delegating to a user account and taking it through the OAuth flow to delegate permissions. It is recommended to have a robot account with restricted permissions to control access and avoid lockouts if a user account experiences problems.

To setup this account, you'll need to take the following steps:

  1. Create a new GSuite account with readonly access to the API on Google Groups. We'll call this the "robot" account. It should have the following permissions:

    • https://www.googleapis.com/auth/admin.directory.group.readonly
    • https://www.googleapis.com/auth/admin.directory.group.member.readonly

Please refer to the GSuite documentation, as the exact process for doing this may have changed. 2. Create a GCP service account in the GCP project where you're interested in using the GSuite "robot" account. Enable G Suite Domain-wide Delegation and note the Client ID. 3. Using the "security" component in the "admin.google.com" console, use the Client ID for the service account and add the following scopes, which are the same as those from step 1: - https://www.googleapis.com/auth/admin.directory.group.member.readonly - https://www.googleapis.com/auth/admin.directory.group.readonly 4. Generate the service account credentials. Make sure to save the generated JSON file somewhere safe.

Once we have the account setup we can modify the deployment to allow rbacsync to use it. The first step is creating the secret from the service account credentials created in step 5:

kubectl create secret generic --from-file=token.json=<my service account credentials path> rbacsync-gsuite-credentials

We can then apply the following diff to the rbacsync deployment to use the secret created above:

@@ -14,6 +14,10 @@
     spec:
       restartPolicy: Always
       serviceAccountName: rbacsync
+      volumes:
+      - name: rbacsync-gsuite-credentials
+        secret:
+          secretName: rbacsync-gsuite-credentials
       containers:
       - name: rbacsync
         image: cruise/rbacsync:latest
@@ -24,6 +28,14 @@
         - /bin/rbacsync
         args:
         - "-logtostderr"
+        - "-gsuite.enabled"
+        - "-gsuite.credentials"
+        - "/run/secrets/gsuite/token.json"
+        - "-gsuite.delegator"
+        - "my-rbacsync-robot@getcruise.com"
+        volumeMounts:
+        - mountPath: /run/secrets/gsuite
+          name: rbacsync-gsuite-credentials
         imagePullPolicy: Always
         ports:
         - name: debug-port

In the above, we set several flags to pass to rbacsync:

  • -gsuite.enabled: enables the GSuite upstream for groups.
  • -gsuite.credentials: path to the credentials generated for the service account. We map them to the secret volume mount location above.
  • -gsuite.delegator: This is the delegator whom the service account acts on behalf of. We call this the "robot" account in the instructions above. Be sure to set the argument to whatever account you use.

NOTE: You can also use -gsuite.pattern to limit which group names are sent upstream for queries. That takes a regular expression that must be matched before it will be allowed to query the upstream.

Once the above is configured and deployed, groups referenced in bindings will be automatically queried against GSuite. If memberships have the same name as an upstream group, the subject lists from the upstream and the memberships section will be merged.

Deployment

WARNING: Before running any commands here, make sure you are in the right cluster context. This will deploy to whatever cluster kubectl is currently configured for.

You can deploy the rbacsync with the following command:

kubectl apply -f deploy/

Once it has been deployed, you'll need to push a config to specify group members using the CRDs defined in this project. There are two CRDs defined depending on whether you want to create groups with cluster scope or namespace

Extension points exported contracts — how you extend this code

Grouper (Interface)
Grouper returns the members of a group, as RBAC Subjects, given a group name. If the group is unknown to the grouper, t [4 …
pkg/groups/grouper.go

Core symbols most depended-on inside this repo

newUserSubject
called by 40
pkg/controller/util.go
newBinding
called by 36
pkg/controller/util.go
newUserSubject
called by 23
pkg/groups/subjects.go
DeepEqual
called by 19
pkg/checks/checks.go
Err
called by 17
pkg/checks/checks.go
newMembership
called by 15
pkg/controller/util.go
resolveGroups
called by 10
pkg/controller/controller.go
Members
called by 8
pkg/groups/grouper.go

Shape

Method 164
Function 77
Struct 32
Interface 22
FuncType 3
TypeAlias 1

Languages

Go100%

Modules by API surface

pkg/generated/clientset/versioned/typed/rbacsync/v1alpha/rbacsyncconfig.go23 symbols
pkg/generated/clientset/versioned/typed/rbacsync/v1alpha/clusterrbacsyncconfig.go23 symbols
pkg/apis/rbacsync/v1alpha/zz_generated.deepcopy.go20 symbols
pkg/generated/informers/externalversions/factory.go16 symbols
cmd/rbacsync/prometheus.go16 symbols
pkg/controller/controller_test.go15 symbols
pkg/controller/controller.go14 symbols
pkg/generated/listers/rbacsync/v1alpha/rbacsyncconfig.go13 symbols
pkg/generated/clientset/versioned/typed/rbacsync/v1alpha/rbacsync_client.go11 symbols
pkg/generated/clientset/versioned/typed/rbacsync/v1alpha/fake/fake_rbacsyncconfig.go10 symbols
pkg/generated/clientset/versioned/typed/rbacsync/v1alpha/fake/fake_clusterrbacsyncconfig.go10 symbols
pkg/generated/clientset/versioned/clientset.go10 symbols

For agents

$ claude mcp add rbacsync \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page