Securing Jenkins with Role-based Access Control and Azure Active Directory

With the ability to effectively scale Jenkins and use it as an orchestrator between many different protected environments and systems, security and proper authorization quickly becomes an important factor to control within Jenkins. Oftentimes, developers work on multiple projects which may span across different masters. Role Based Access Control coupled with Azure Active Directory (Azure AD) can help you implement and manage a comprehensive authorization strategy for Jenkins, while integrating with the rest of your Single Sign-On ecosystem as defined by Azure AD. This security setup can be set on individual masters or across multiple masters managed by Cloudbees Jenkins Operations Center.

What is Role-based Access Control (RBAC)?

Role-based Access Control (RBAC) is a feature of the Cloudbees Jenkins Platform that allows administrators to define general security roles that will apply to the system that they administer. Once roles have been defined, the Jenkins administrator can assign those roles to groups of users, which can be defined either on the global level or down to the specific project or job level. RBAC integrates nicely with many underlying authentication mechanisms such as Active Directory, LDAP, or in this case Azure AD. RBAC’s default behavior is to propagate permissions, but there is also the ability to ignore the inherited permissions for specific projects which in turn completely hides the project from any group not specifically defined for that project. This functionality brings unprecedented flexibility for managing a large number of jobs.

What is Azure Active Directory (Azure AD)?

Azure AD is Microsoft’s multi-tenant cloud based directory and identity management service. Azure AD provides a single sign-on (SSO) solution for thousands of cloud SaaS Applications including Jenkins. Azure AD can also integrate with an existing on-premise Windows Server Active Directory to use the identities defined there for SSO. While Azure AD is based on Active Directory, it exposes SAML as its primary protocol for external application interaction.

Getting Started

Requirements

  1. JDK 1.7+
  2. Cloudbees Jenkins Platform
    • SAML Plugin
  3. Azure AD Subscription or Trial

Initial Setup

  • Install SAML Plugin- Login to Jenkins Operations Center or Jenkins Enterprise, go to Manage Jenkins > Manage Plugins > Available, select the SAML plugin and then the ‘Download now and Install after Restart’ button. Restart Jenkins after the updates are complete. As of this writing the latest version is 0.4
  • Azure AD- Login to your Azure account by clicking here and navigate to your Active Directory Instance or create a new instance. Ensure that there are some users and groups already created within the Azure AD instance. Click here for help on getting started with Azure AD.

Set Up Azure AD

In the Azure AD management portal go to Active Directory > [Directory] > Applications section, select Add, and then Add an application my organization is developing.

Enter the Name of the application and select Web Application and/or Web API and click NextThe sign-on URL and App ID URI should be set to http://[Jenkins Address]/securityRealm/finishLogin

The Application should be created now! If you would like to use groups defined in Azure AD within Jenkins, you will need to enable “Group Claims” so that Azure AD can also send over the group membership information for users to Jenkins.

Click Manage Manifest > Download Manifest from the application screen that was just created.

The Manifest is a standard JSON file that can be opened using any editor like Notepad. Open the Manifest and scroll to the groupMembershipClaims property. Change this property value from the default null to “SecurityGroup” as shown below

Save the Manifest file and go back to the Azure Dashboard click on Manage Manifest > Upload Manifest and browse to the modified Manifest to upload it. Now Azure AD has been set up to send group membership information for users to Jenkins.

From the Application Get Started page there should be a Federation Metadata Document URL. Copy that URL and go to the URL in another tab. It should display the Federation Metadata XML document. Leave this open as it will be needed when configuring the SAML settings within Jenkins.

Configure Cloudbees Jenkins Platform to login with Azure AD

In Jenkins, navigate to Jenkins > Configure Global Security. Check the box that says “Enable Security”. Under Security Realm select SAML 2.0.
For IdP metadata: copy and paste the contents of the Federation Metadata XML file that was opened in the previous step.  
Set the Group Attribute to: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups as shown below.

Click save. You should now be able to login to Jenkins with users authenticated with Azure AD.

Configure Role Based Access Control with Azure AD Users/Groups

In Jenkins, navigate to Jenkins > Configure Global Security. Under Authorization select Role-based matrix authorization strategy and click Save. Create the appropriate Groups and Roles as defined in the documentation.
To add an Azure AD User or Group to an RBAC Group, select the specified group and click Add user/group. For the ID, insert the “Object ID” of Azure AD user or group. The Object ID can be found by navigating to the Properties of the User/Group in Azure AD as can be seen below. Note: the reason Object ID must be used is due to the fact that Azure AD only sends over the Object ID because the “name” may change but the Object ID is always static.

Once the appropriate roles and groups are set up within RBAC, the setup is complete and users will now be able to log into their appropriate projects using Azure AD.

Conclusion

With the combination of Role Based Access Control and Azure AD, it becomes very easy to create a flexible and robust authorization strategy for Jenkins. You can now login to Jenkins using the same credentials that are used for many other applications within your organization which are all managed from one central dashboard.

References

https://azure.microsoft.com/en-us/documentation/articles/active-directory-whatis/
http://justazure.com/azure-active-directory-part-4-group-claims/
http://blog.cloudbees.com/2011/05/squeeze-more-juice-out-of-jenkins.html

 
Isaac Cohen
Solutions Architect
CloudBees

Comments

• When I did copy and paste the full xml document into the idp metadata field in Jenkins it didn’t work the first time. It turns out I picked up the <?xml version="1.0" encoding="UTF-8"?> tag. I had to remove that first line. Your first line should start with "<EntityDescriptor ... " and the last line should end with "</EntityDescriptor>" • I did not have read access to the Azure AD to copy the “Object ID” as specified. However I found out I didn’t need it. I achieve the following behavior for first time user sign-in: 1. The first time a user successfully signs in, a new user id is established in Jenkins. The Jenkins user id is a long random set of characters like “OKkAa-RtOZrgT6ikj6UOiYndIFIvWwmYTCvbGE7UNfc”, (I’ve been told this is the object id passed from Azure AD) and the user name is what the user authenticated as (For example YourUserid@safeway.com) 2. Once the user has been establish in Jenkins, the Jenkins administrator must add that user id (the long random set of characters) to the appropriate Jenkins group (Jenkin Role-based matrix authorization strategy). Happily, what is display in the Jenkins group after the add is the user name (YourUserid@safeway.com) not the user id (OKkAaRtOZrgT6ikj6UOiYndIFIvWwmYTCvbGE7UNfc) 3. When the user signs out then signs back in, unless they clear the browser “cache”, there is no user authentication check required (some kind of security token is cached).

Thanks for these 2 suggestions! Yes, when you are copying over the xml document you want to make sure that it begins and ends with the "EntityDescriptor" tag and no other extraneous tags like the prolog (the version and encoding that you saw). Also, that is definitely another way of getting the "Object ID" if you do not have access to the Azure AD instance. Your machine will cache the authentication cookie until it expires as defined by the Azure AD SSO.

Regarding the long random username you can solve it by setting the "Username Attribute" to http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress

We were seeing login errors after using this guide, saying that <some long hash> didn't have overall/read permissions. This is because Jenkins isn't looking for the correct user id as configured. If you want to be able to use the object id's as mentioned in the guide, change: Display Name Attribute to "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" Group Attribute to "http://schemas.microsoft.com/ws/2008/06/identity/claims/groups" Username Attribute to "http://schemas.microsoft.com/identity/claims/objectidentifier" You can then use group object ID's and user object ID's for users/groups within jenkins. The Azure AD email address for the user will be used as the display name. Hope this helps anyone going around in circles like we were.

Add new comment