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.
Prerequisites
The following software and plugins must be installed to use RBAC with CasC:
-
If using CloudBees CI 2.249.3.1 - 2.303.3.3: CloudBees CasC API (Deprecated) plugin, version 1.2 - 1.41
-
If using CloudBees CI 2.319.1.5 or later: CloudBees CasC Client plugin, version 1.44 or later
Required setup
You can define groups and roles at the controller-level using the Configuration as Code rbac.yaml
file.
-
Controller authorization strategy: To apply RBAC settings (
rbac.yaml
) to a controller using CasC, the controller’s authorization strategy must not be inherited from operations center. For more information, see Configuring the controller authorization strategy. -
User management: Users need to be created in your CloudBees CI system either by an identity provider (like LDAP) or manually. The examples below assume the users exist.
-
Item management: To apply RBAC groups and/or roles to items, the CasC configuration bundle must include an
items.yaml
file with the defined items.
For more information, refer to Creating items with CasC for controllers.
Configuring the controller authorization strategy
To apply RBAC settings (rbac.yaml
) to an individual controller using Configuration as Code, the controller’s authorization strategy must not be inherited from the operations center.
If groups and roles are defined in the operations center or if RBAC is only used with the items.yaml file, you do not need to opt out of inheriting the operations center’s authorization strategy.
|
To configure the controller authorization strategy:
-
Ensure you are signed in to the operations center as a user with the Administer permission.
-
From the operations center dashboard, in the left pane, select Manage Jenkins.
-
Select Configure Global Security.
-
Scroll down to Client controller security and select Allow client controllers to opt-out.
-
Select Save.
For more information on how to customize the authorization strategy for an individual controller, refer to Configuring SSO in the operations center. -
From the operations center dashboard, select the down arrow to the right of your controller’s name, and then select Configure.
Figure 1. Controller dropdown menu -
Scroll down to Security Setting Enforcement and select either Enforce Authentication only or Opt out of all security enforcement.
For more information on how to customize the authorization strategy for an individual controller, refer to Configuring options for individual controllers.
Exporting RBAC configurations
You can export Role-Based Access Control (RBAC) configurations from an existing controller. 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 items
Example bundle.yaml file
id: "remove-bundle" version: "1" apiVersion: "1" description: "CasC bundle with removeStrategy in descriptor" allowCapExceptions: true availabilityPattern: "folder1/.*" parent: "bundle-global" jcasc: - "jenkins.yaml" jcascMergeStrategy: "errorOnConflict" plugins: - "plugins.yaml" catalog: - "plugin-catalog.yaml" itemRemoveStrategy: items: "remove-all" rbac: "sync" rbacRemoveStrategy: "sync" items: - "items.yaml" rbac: - "rbac.yaml" variables: - "variables.yaml"
Example jenkins.yaml file
jenkins: systemMessage: "Controller 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) globalCloudBeesPipelineTemplateCatalog:(2) catalogs: - branchOrTag: "main" scm: git: credentialsId: "credentials-id" id: "cf504eg3-4y5d-34w2-97b1-2q7xt2nm9731"(3) remote: "git@github.com:company/project-alpha.git" updateInterval: "1d"
1 | Required to use CloudBees RBAC configured using CasC. |
2 | Required if using CasC to create a job based on a Pipeline Template Catalog. |
3 | Required property that defines the unique ID for the SCM repository where the Pipeline Template Catalog is stored. |
Example plugins.yaml file
plugins: # In CloudBees Assurance Program (CAP) - id: "bitbucket-branch-source" - id: "branch-api" - id: "cloudbees-casc-client" - id: "cloudbees-casc-items-api" - id: "cloudbees-casc-items-commons" - id: "cloudbees-casc-items-controller" - id: "cloudbees-template" - id: "cloudbees-workflow-template" - id: "configuration-as-code" - id: "git" - id: "github-branch-source" - id: "infradna-backup" - id: "support-core" - id: "workflow-multibranch" # Not in CAP (see plugin-catalog.yaml) - id: "manage-permission"
Example plugin-catalog.yaml file
type: "plugin-catalog" version: "1"(1) name: "my-plugin-catalog" displayName: "My Plugin Catalog" configurations: - description: "Extensions to CAP" includePlugins: manage-permission:(2) version: 1.0.1(3) #my-custom-plugin: #url: http://www.example.org/jenkins-plugins/my-custom-plugin-1.2.3.hpi beekeeperExceptions: support-core: version: "2.70"
1 | version (required) - must currently have the value 1, which defines the current metadata format for the plugin catalog. |
2 | Add the manage-permission plugin to enable the Overall/Manage permission. |
3 | Replace 1.0.1 with the most recent version. |
Example items.yaml file
If a CloudBees CI GitHub Organization is used to configure a repository from a GitHub Enterprise server and you add the server to the Configure System screen, API endpoint is a required field. You must verify that the apiUri property is configured in the items.yaml file. If the GitHub server is not an enterprise server, you can optionally remove the apiUri property from the items.yaml file.
|
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: "pipeline" name: "project-beta-pipeline-job" displayName: "Project Beta Pipeline job" description: "This is Project Beta's Pipeline job!" definition: cpsScmFlowDefinition: scriptPath: "Jenkinsfile" scm: gitSCM: gitTool: "git" userRemoteConfigs: - userRemoteConfig: name: "developer-b" credentialsId: "credentials-id" url: "git@github.com:company/project-beta.git" extensions: - checkoutOption: timeout: 2 - cloneOption: reference: "/workspace/git" noTags: false honorRefspec: false shallow: true timeout: 5 branches: - branchSpec: name: "*/main"
removeStrategy: items: "none" rbac: "sync" items: - kind: "multibranch" name: "project-beta-multibranch-pipeline" displayName: "Project Beta Multibranch Pipeline" description: "This is Project Beta's Multibranch Pipeline job!" orphanedItemStrategy: defaultOrphanedItemStrategy: pruneDeadBranches: true daysToKeep: 3 numToKeep: 4 projectFactory: workflowBranchProjectFactory: scriptPath: "Jenkinsfile" sourcesList: - branchSource: source: github: traits: - gitHubBranchDiscovery: strategyId: 1 - gitHubPullRequestDiscovery: strategyId: 1 - gitHubForkDiscovery: trust: gitHubTrustEveryone: {} strategyId: 1 - headWildcardFilter: excludes: "feature/*" includes: "*" - gitHubSshCheckout: credentialsId: "github-ssh" repoOwner: "company" id: "scm-source-id" repository: "project-alpha" configuredByUrl: true repositoryUrl: "https://github.com/company/project-beta" strategy: allBranchesSame: {}
removeStrategy: items: "none" rbac: "sync" items: - kind: "organizationFolder" name: "project-alpha-github-org" displayName: "Project Alpha GitHub Organization job" description: "This is Project Alpha's Github Organization job!" navigators: - github: traits: - checkoutOptionTrait: extension: checkoutOption: timeout: 5 - cloneOptionTrait: extension: cloneOption: reference: main noTags: false honorRefspec: false shallow: true timeout: 6 repoOwner: "company" projectFactories: - customMultiBranchProjectFactory: factory: customBranchProjectFactory: marker: ".my-marker-file" definition: cpsScmFlowDefinition: scriptPath: "pipelines/default/Jenkinsfile" scm: gitSCM: extensions: - checkoutOption: timeout: 4 gitTool: "git" userRemoteConfigs: - userRemoteConfig: name: "admin-a" credentialsId: "credentials-id" url: "git@github.com:company/project-alpha.git" browser: githubWeb: repoUrl: "git@github.com:company/project-alpha" branches: - branchSpec: name: "*/main" lightweight: false
removeStrategy: items: "none" rbac: "sync" items: - kind: "organizationFolder" name: "project-beta-bitbucket-org" displayName: "Project Beta Bitbucket Organization job" description: "This is Project Beta's Bitbucket Organization job!" navigators: - bitbucket: traits: - bitbucketBranchDiscovery: strategyId: 1 - bitbucketPullRequestDiscovery: strategyId: 1 - bitbucketForkDiscovery: trust: bitbucketTrustTeam: {} strategyId: 1 repoOwner: "company" projectFactories: - workflowMultiBranchProjectFactory: scriptPath: "Jenkinsfile"
removeStrategy: items: "none" rbac: "sync" items: - kind: "cloudbeesTemplatedJob" name: "job-template-alpha" model: "folder1/template"(1) attributes:(2) - value: job-template-alpha(3) key: name - value: the description key: description - value: pwd key: command
1 | The full path to the template. |
2 | Attributes defined in the CloudBees job template. |
3 | The name of the new instance you are creating based on the template. |
removeStrategy: items: "none" rbac: "sync" items: - kind: "cloudbeesTemplatedJob" name: "my-new-job" catalog: "project-alpha-pipeline-template-catalog"(1) model: "template-alpha"(2) attributes:(3) - value: template-alpha(4) key: name - value: the description key: description - value: pwd key: command
1 | The name of the Pipeline Template Catalog that is defined in the catalog.yaml file. |
2 | The name of the template within the Pipeline Template Catalog. |
3 | Attributes defined in the CloudBees job template. |
4 | The name of the new job you are creating based on the template. |
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
removeStrategy: items: "none" rbac: "sync" items: - kind: backupAndRestore name: project-alpha-restore displayName: "Project Alpha restore" description: "This is Project Alpha's restore job!" buildersList: - restoreBuilder: ignoreConfirmationFile: false preserveJenkinsHome: true ignoreDigestCheck: true store: s3Store: bucketName: bucket sse: true bucketFolder: bucketFolder credentialsId: testCredential region: us-east-1 restoreDirectory: /tmp label: agent-for-restore 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". |