Configuring RBAC with CasC for the operations center

7 minute readScalabilityAutomation

You can configure global role-based access control (RBAC) by adding the rbac.yaml file to the configuration bundle. Additionally, the authorizationStrategy attribute must be added to the jenkins.yaml file.

If the operations center items.yaml file is used to create controller items, the controller RBAC configuration is defined in the operations center items.yaml file.

Prerequisites

The following software and plugins must be installed to use RBAC with CasC:

Required setup

  • User management: You must create users in your CloudBees CI system, either using an identity provider (like LDAP) or manually creating them. The examples below assume the users exist.

  • Item management: You must include an items.yaml file in the controller CasC bundle to apply RBAC groups and/or roles to items.

For more information, refer to Creating items with CasC for the operations center.

Exporting RBAC configurations

You can export role-based access control (RBAC) configurations from an existing operations center instance. For more information, refer to Exporting a CasC configuration.

The exported file should be used as a starting point, as it may require modifications and adjustments to make it production-ready.

Example CasC configuration bundle with RBAC

Example bundle.yaml file

id: "bundle-1"
version: "1"
apiVersion: "1"
description: "My CloudBees Configuration as Code (CasC) bundle"
jcasc:
  - "jenkins.yaml"
jcascMergeStrategy: "errorOnConflict"
plugins:
  - "plugins.yaml"
items:
  - "items.yaml"
rbac:
  - "rbac.yaml"
variables:
  - "variables.yaml"

Example jenkins.yaml file

jenkins:
  systemMessage: "Operations center configured using CloudBees CasC"
  numExecutors: 0
    securityRealm:
    ldap:
      configurations:
      - displayNameAttributeName: "cn"
        groupMembershipStrategy:
          fromGroupSearch:
            filter: "member={0}"
        groupSearchBase: "ou=Groups"
        inhibitInferRootDN: false
        managerDN: "cn=admin,dc=example,dc=org"
        managerPasswordSecret: ${LDAP_MANAGER_PASSWORD}
        rootDN: "dc=example,dc=org"
        server: "ldap://ldap-openldap:389"
        userSearchBase: "ou=People"
      disableMailAddressResolver: false
      groupIdStrategy: "caseInsensitive"
      userIdStrategy: "caseInsensitive"
  authorizationStrategy: "cloudBeesRoleBasedAccessControl" (1)
security:
  securitySettingsEnforcement:
    global:
      realmAndAuthorization:
        canCustomMapping: false
        canOverride: true
        defaultMappingFactory: "restrictedEquivalentRAMF"
  controllerExecutorCount:
    enforce:
      canOverride: false
      count: 0
cloudBeesCasCServer:
  visibility: true (2)
unclassified:
  cascAutoControllerProvisioning:
    provisionControllerOnCreation: true (3)
    fireAndForget: true (4)
    initialDelay: 15  (5)
    timeout: 600 (6)
    duration: 60 (7)
  location:
    url: https://operations-center:8888/ (8)
  bundleStorageService: (9)
    activated: true
    activeBundle:
      name: "local-folder"
      retriever:
        SCM:
          scmSource:
            git:
              id: "acf88621-05a0-4d50-9166-d7767868dc43"
              remote: "https://github.com/my-company/repo.git"
              traits:
              - "gitBranchDiscovery"
    pollingPeriod: 0
    purgeOnDeactivation: false
1 Required to use CloudBees RBAC configured using CasC.
2 Optional if using the items.yaml file to create a controller item. When visibility is set to true, all CasC bundles that do not have an availability pattern defined can be used by any controller. This option provides more flexibility, but is less secure.
3 When provisionControllerOnCreation is set to true, all managed controller items are provisioned automatically after they are created using CasC.
4 When fireAndForget is set to true, the automatic provisioning process starts immediately, and does not wait for the controller to be connected.
5 The amount of time, in seconds, to wait before starting the automatic provisioning process.
6 The amount of time, in seconds, to complete the automatic provisioning process. If fireAndForget is set to false, this timeout may prevent queued provisioning requests from being blocked.
7 The provisioning duration, in seconds. After the initial delay, controllers are provisioned at random in batches of 20 controllers, for this time period. Increase this value to increase the amount of time between controller provisioning requests. If provisioning more than 20 controllers, the provisioning process will exceed the specified duration.
8 Required to create client controller items. The url is the operations center URL.
9 Required if using a local folder on the operations center server or an SCM tool as the Configuration as Code bundle location.

Example plugins.yaml file

plugins:
  # In CAP
  - id: "cloudbees-casc-client"
  - id: "cloudbees-casc-items-api"
  - id: "cloudbees-casc-items-commons"
  - id: "cloudbees-casc-items-server"
  - id: "configuration-as-code"
  - id: "operations-center-rbac"

Example items.yaml file

  • If creating a new controller item, refer to Creating a new controller item using CasC for the operations center.

  • By default, shared agent and shared cloud agent items are configured to be taken online. To configure the shared agent or shared cloud agent item to be taken offline, add the takeOnline property to the items.yaml and set it to false. For example: takeOnline: false.

Folders with limited fields
Folders with extended fields
Freestyle job
Cluster operations
Managed controller
Client controller
Shared agent
Shared cloud agent
Backup
removeStrategy:
  items: "none"
  rbac: "sync"

items:
  - kind: "folder"
    name: project-${team_group}
    displayName: "Project Alpha"
    description: "Project Alpha is going to change the world!"
    properties:
      - folderCredentialsProperty:
          folderCredentials:
            - credentials:
                - usernamePassword:
                    password: ${secret_location}
                    scope: GLOBAL
                    description: description
                    id: test-id
                    usernameSecret: false
                    username: test-user
              domain: {}
    groups:
      - name: "Project Alpha Developers"
        members:
          external_groups:
            - ldap-project-${team_group}
        roles:
          - name: "developer"
    items: (1)
      - kind: "folder"
        name: "project-alpha-tests"
        displayName: "Project Alpha Tests"
        items:
          - kind: "folder"
            name: "test-1"
          - kind: "folder"
            name: "test-2"
  - kind: "folder"
    name: "project-beta"
    displayName: "Project Beta"
    description: "Secret project! Only Admins can see this!"
    filteredRoles: (2)
      - "developer"
      - "browser"
1 Items can be nested within other items, enabling users to create a folder structure.
2 Roles can be filtered, for example to allow only administrators to view certain projects.
removeStrategy:
  items: "none"
  rbac: "sync"

items: (1)
  - kind: "folder"
    name: project-${team_group}
    displayName: "Project Alpha"
    description: "Project Alpha is going to change the world!"
    groups:
      - name: "Project Alpha Developers"
        members:
          external_groups:
            - ldap-project-${team_group}
        roles:
          - name: "developer"
    items:
      - kind: "folder"
        name: "project-alpha-tests"
        displayName: "Project Alpha Tests"
        items:
          - kind: "folder"
            name: "test-1"
          - kind: "folder"
            name: "test-2"
    properties:
      - envVars:
          vars:
            FOO: "BAR"
            BAR: "BAZ"
      - folderLibraries:
          libraries:
            - libraryConfiguration:
                implicit: false
                allowVersionOverride: true
                retriever:
                  modernSCM:
                    scm:
                      github:
                        traits:
                          - gitHubBranchDiscovery:
                              strategyId: 1
                          - gitHubPullRequestDiscovery:
                              strategyId: 1
                          - gitHubForkDiscovery:
                              trust:
                                gitHubTrustEveryone: {}
                              strategyId: 1
                        repoOwner: "company"
                        id: "library-id"
                        repository: "project-alpha"
                        configuredByUrl: true
                        repositoryUrl: "https://github.com/company/project-alpha"
                name: "my-library"
                includeInChangesets: true
      - folderCredentialsProperty:
          folderCredentials:
            - credentials:
                - usernamePassword:
                    password: ${secret_location}
                    scope: GLOBAL
                    description: description
                    id: test-id
                    usernameSecret: false
                    username: test-user
              domain: {}
      - itemRestrictions:
          allowedTypes:
            - "org.jenkinsci.plugins.workflow.job.WorkflowJob"
            - "hudson.matrix.MatrixProject"
            - "hudson.model.FreeStyleProject"
            - "com.cloudbees.hudson.plugins.modeling.impl.jobTemplate.JobTemplate"
            - "com.cloudbees.hudson.plugins.folder.Folder"
            - "com.cloudbees.hudson.plugins.modeling.impl.builder.BuilderTemplate"
            - "com.cloudbees.hudson.plugins.modeling.impl.auxiliary.AuxModel"
            - "org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject"
            - "com.cloudbees.hudson.plugins.modeling.impl.publisher.PublisherTemplate"
            - "com.cloudbees.hudson.plugins.modeling.impl.folder.FolderTemplate"
            - "com.infradna.hudson.plugins.backup.BackupProject"
          filter: true
    items:
      - kind: "freeStyle"
        name: "project-alpha-freestyle"
        displayName: "Freestyle job in the Project Alpha folder"
  - kind: "folder"
    name: "project-beta"
    displayName: "Project Beta"
    description: "Secret project! Only Admins can see this!"
    filteredRoles: (2)
      - "developer"
      - "browser"
1 Items can be nested within other items, enabling users to create a folder structure.
2 Roles can be filtered, for example to allow only administrators to view certain projects.
removeStrategy:
  items: "none"
  rbac: "sync"

items:
  - kind: "freeStyle"
    name: "project-alpha-freestyle"
    displayName: "Project Alpha Freestyle"
    description: "This is Project Alpha's Freestyle job!"
    disabled: false
    scm:
      gitSCM:
        extensions:
          - checkoutOption:
              timeout: 4
        gitTool: git
        userRemoteConfigs:
          - userRemoteConfig:
              name: "developer-a"
              credentialsId: "credentials-id"
              url: "git@github.com:company/project-alpha.git"
        browser:
          githubWeb:
            repoUrl: "https://github.com/company/project-alpha"
        doGenerateSubmoduleConfigurations: false
        branches:
          - branchSpec:
              name: "*/main"
    buildDiscarder:
      logRotator:
        artifactDaysToKeep: 3
        daysToKeep: 1
        numToKeep: 2
        artifactNumToKeep: 4
    scmCheckoutStrategy:
      standard: { }
    builders:
      - shell:
          command: "pwd"
removeStrategy:
  items: "none"
  rbac: "sync"

items:
  - kind: clusterOpProject
    name: "project-alpha-cluster-operations"
    displayName: "Project Alpha - Cluster operations"
    description: "These are Project Alpha's cluster operations!"
	disabled: false
    concurrentBuild: true
	operations:
      - masterClusterOperation:
          failureMode: IMMEDIATELY
          clusterOpSteps:
            - backupClusterOpStep:
                subjects:
                  - buildRecordSubject: {}
                  - jobConfigurationSubject: {}
                format:
                  zipFormat: {}
                retentionPolicy:
                  exponentialDecayRetentionPolicy: {}
                safeDelaySeconds: 10
                store:
                    s3Store:
                        bucketName: ' mybucket'
                        sse: true
                        bucketFolder: somefolder
                        credentialsId: 'my-aws-credentials-id'
                        region: us-east-1
          timeoutSeconds: 0
          itemSource:
              jenkinsRootItemSource: {}
          filters:
            - isMasterOnlineFilter: {}
          inParallel: 0
          noRetries: 0
removeStrategy:
  items: "none"
  rbac: "sync"

items:
  - kind: managedController
    displayName: "managed-controller-alpha"
    name: "managed-controller-alpha"
    description: "This is Project Alpha's managed controller!"
    groups:
      - name: "Project Alpha Developers"
        members:
          users:
            - developer-1
        roles:
          - name: developer
    properties:
      - configurationAsCode:
          bundle: bundle-1
      - healthReporting:
          enabled: false
      - owner:
          delay: 5
          owners: ''
      - envelopeExtension:
          allowExceptions: false
      - sharedConfigurationOptOut:
          optOut: false
      - licensing:
          strategy:
            perUserLicensingStrategy: {}
    configuration:
      kubernetes:
        allowExternalAgents: false
        terminationGracePeriodSeconds: 1200
        #image: cloudbees/mc-foo-image # uncomment to use a non-default image
        memory: 3072 (1)
        fsGroup: '1000'
        cpus: 1.0
        readinessTimeoutSeconds: 5
        livenessInitialDelaySeconds: 300
        readinessInitialDelaySeconds: 30
        clusterEndpointId: default
        disk: 50
        readinessFailureThreshold: 100
        livenessTimeoutSeconds: 10
        domain: managed-controller-alpha
        livenessPeriodSeconds: 10
        javaOptions: -DfooSystemProperty="foo" -Dbar="bar"
        yaml: |-
          ---
          apiVersion: apps/v1
          kind: StatefulSet
          metadata:
            labels:
              my-label: my-value
1 Some settings, such as controller memory, require the controller to be re-provisioned for the setting to take effect.
removeStrategy:
  items: "none"
  rbac: "sync"

items:
  - kind: clientController
    displayName: "client-controller-beta"
    name: "client-controller-beta"
    description: "This is Project Beta's client controller!"
    groups:
      - name: "Project Beta Developers"
        members:
          users:
            - developer-1
        roles:
          - name: developer
    properties:
    - configurationAsCode:
        bundle: bundle-2
    - healthReporting:
        enabled: false
    - owner:
        delay: 5
        owners: ''
    - envelopeExtension:
          allowExceptions: false
    - sharedConfigurationOptOut:
          optOut: false
    - licensing:
        strategy:
          perUserLicensingStrategy: {}
    - webSocket:
        enabled: true
removeStrategy:
  items: "none"
  rbac: "sync"

items:
  - kind: "sharedAgent"
    displayName: "Shared Agent for this cluster"
    name: "shared-agent-1"
    description: "Shared Agent for this cluster"
    remoteFS: "/tmp/remote"
    properties:
      - sharedAgent:
          customizers:
            - envVars:
                value:
                  SKIP_RELEASE: "TRUE"
                  JENKINS_VERSION: "2.303"
            - toolLocation:
                value:
                  - name: "git"
                    type: "git"
                    home: "/usr/local/git"
                  - name: "maven3"
                    type: "mvn"
                    home: "/usr/local/mvn"
    labels: "ubuntu"
    launcher:
      inboundAgent:
        webSocket: true
        workDirSettings:
          remotingWorkDirSettings:
            internalDir: "/path/to/directory"
            disabled: false
            failIfWorkDirIsMissing: true
            workDirPath: "/path/to/directory"
        agentStartupOptions: "-noCertificateCheck"
        vmargs: "-Xms2G -Xmx2G"
        tunnel: "192.1.1.45:22"
    mode: EXCLUSIVE
    numExecutors: 10
    retentionStrategy:
      sharedNodeRetentionStrategy: {}
removeStrategy:
  items: "none"
  rbac: "sync"

items:
  - kind: "sharedCloud"
    displayName: "Shared Cloud Agent for this cluster"
    name: "shared-cloud-1"
    description: "Shared Cloud Agent for this cluster"
    properties:
      - sharedCloud:
          customizers:
            - envVars:
                value:
                  SKIP_RELEASE: "TRUE"
                  JENKINS_VERSION: "2.303"
            - toolLocation:
                value:
                  - name: "git"
                    type: "git"
                    home: "/usr/local/git"
                  - name: "maven3"
                    type: "mvn"
                    home: "/usr/local/mvn"
    cloud:
      inboundAgents:
        mode: EXCLUSIVE
        numExecutors: 10
        remoteFS: "/path/to/directory"
        labels: "ubuntu"
        launcher:
          inboundAgent:
            webSocket: true
            workDirSettings:
              remotingWorkDirSettings:
                internalDir: "/path/to/directory"
                disabled: false
                failIfWorkDirIsMissing: true
                workDirPath: "/path/to/directory"
            agentStartupOptions: "-noCertificateCheck"
            vmargs: "-Xms2G -Xmx2G"
            tunnel: "192.1.1.45:22"
removeStrategy:
  items: "none"
  rbac: "sync"

items:
  - kind: backupAndRestore
    name: project-alpha-backup
    displayName: "Project Alpha backup"
    description: "This is Project Alpha's backup job!"
    buildersList:
      - backupBuilder:
          subjects:
            - buildRecordSubject:
                excludes: foo
            - jobConfigurationSubject:
                excludes: bar
            - systemConfigurationSubject:
                excludes: baz
                omitMasterKey: true
          format:
            zipFormat: {}
          exclusive: false
          store:
            s3Store:
              bucketName: bucket
              sse: true
              bucketFolder: bucketFolder
              credentialsId: testCredential
              region: us-east-1
          retentionPolicy:
            exponentialDecayRetentionPolicy: {}
          safeDelaySeconds: 42
    label: agent-for-backup
    triggers:
      - cron:
          spec: 0 0 * * *
    buildDiscarder:
      logRotator:
        numToKeep: 5

Example rbac.yaml file

removeStrategy:
  rbac: "SYNC" (1)

roles:
  - name: administer
    permissions:
      - hudson.model.Hudson.Administer
  - name: developer
    permissions:
      - hudson.model.Hudson.Read
      - hudson.model.Item.Read
      - hudson.model.Item.Create
      - hudson.model.Item.Configure
    filterable: "true" (2)
  - name: browser
    permissions:
    - hudson.model.Hudson.Read
    - hudson.model.Item.Read
    filterable: "true"
  - name: authenticated
    filterable: "true"
    permissions:
    - hudson.model.Hudson.Read

groups:
  - name: Administrators
    roles:
      - name: administer
        grantedAt: current (3)
    members:
      users:
        - admin
      external_groups:
        - ${external_admin_group}
  - name: Developers
    roles: (4) (5)
      - name: developer
    members:
      users:
        - developer
      internal_groups:
        - "some-other-group"
      external_groups:
        - "ldap-cb-developers"
  - name: Browsers
    roles:
      - name: browser
    members:
      users:
        - read
1 For security reasons, SYNC is here to remove groups/roles from CloudBees Continuous Integration when they are removed from this file.
2 If filterable is not included, the default value is “false”.
3 Other options that could be used here include: "child" or "grandchild".
4 If propagates is not included, the default value is "true".
5 If grantedAt is not included, the default value is "current".

Example variables.yaml file

  variables:
    - key: value
    - long_text: |-
        multiline string without
        quotes
    - another: text
    - team_name: Team Alpha
    - team_group: alpha
    - external_admin_group: ldap-cb-admins