Skip to content

Azure AD & CloudBees Core

In this article we're going to configure Azure AD as Single-Sign-Solution for CloudBees Core. The configuration rests on three points; 1) Azure AD, 2) Jenkins' SAML plugin, and 3) CloudBees Core's Role Base Access Control or RBAC for short.

Important

Currently there's a discrepency between the TimeToLive (TTL) of the RefreshToken in Azure AD and the default configuration in the SAML plugin.

This creates the problem that you can be logged in, in Azure, but when going to Jenkins you get the Logged Out page. The only way to log back in, is to logout in Azure and back in.

The reason is as follows:

The max lifetime of the Access Token in Azure AD seems to be 24 hours where the refresh token can live for a maximum of 14 days (if the access token expires the refresh token is used to try to obtain a new access token). The Jenkins setting in Configure Global Security > SAML Identity Provider Settings > Maximum Authentication Lifetime is 24 hours (86400 in seconds) upping this to 1209600 (which is 14 days in seconds/the max lifetime of the Refresh Token).

The recommended resolution is to set Maximum Authentication Lifetime to the same value of your RefreshToken TTL. If you haven't changed this in Azure AD, it is 1209600.

Manage Jenkins -> Configure Global Security > SAML Identity Provider Settings > Maximum Authentication Lifetime = 1209600

Prerequisites

Before we start, there are some requirements.

  • a running CloudBees Core Operations Center instance
  • this instance is accessible via https.
  • active Azure subscription
  • have an Azure subscription Administrator on hand

Configure Azure

Warning

We use https://cloudbees-core.example.com as the example URL for CloudBees Core. Please replace the domain to your actual domain in all the examples!

Steps to execute

We do the following steps on the Azure side.

  • create the Azure Active Directory
  • create users and groups
  • create App Registration
    • URL: https://cloudbees-core.example.com/cjoc/securityRealm/finishLogin
    • replace example.com with your domain, https is required!
  • update manifest (for groups)
    • change: "groupMembershipClaims": null, (usually line 11)
    • to: "groupMembershipClaims": "SecurityGroup",
  • create SP ID / App ID URI
  • grant admin consent

Info

If you use the Azure AD plugin, you also create a client secret.

Information To Note Down

The following information is unique to your installation, so you need to record them as you go along.

  • App ID URI
  • Object ID's of Users and Groups you want to give rights
  • Federation Metadata Document Endpoint
    • Azure AD -> App Registrations -> -> Endpoints (circular icon on top)
    • you can use either the URL or the document contents
    • make sure the URL contains the Tenant ID of your Azure Active Directory
    • URL example: https://login.microsoftonline.com/${TENANT_ID}/federationmetadata/2007-06/federationmetadata.xml
    • You can find your Tenant ID in Azure Active Directory -> Properties -> Directory ID (different name, same ID)

Visual Guide

Below is a visual guide with screenshots.

Pay attention to these hints in the screenshots.

  • red: this is the main thing
  • orange: this is how we got to the current page/view
  • blue: while you're in this screen, there might be other things you could do

Create New App Registration

If you have an Azure account, you have an Azure Active Directory (Azure AD) pre-created.

This guide assumes you have an Azure AD ready to use.

That means the next step is to create an Application Registration.

gitops model

Give the registration a useful name, select who can authenticate and the redirect URL.

This URL needs to be configured and MUST be the actual URL of your CloudBees Core installation.

gitops model

Important

To have Client Masters as a fallback for login, incase Operations Center is down, you have to add another redirect URL for each Master.

Azure AD -> App Registrations -> -> Authentication -> Web -> https://example.com/teams-cat/securityRealm/finishLogin

App Registration Data To Write Down

Depending on the plugin you're going to use (SAML or Azure AD) you need information from your Azure AD / App Registration.

  • Tentant ID
  • Object ID
  • Client ID
  • Federation Metadata Document
    • you can use the document XML content or the URL

gitops model

Click on the Endpoints button to open the side-bar with the links.

gitops model

App ID

We need the App ID - even if the SAML plugin doesn't mention it.

Azure generates an APP ID URI for you. You can also use CloudBees Core's URL as the URI. The URI is shown when there is an error, so it recommended to use a value you can recognize.

Info

App ID must match in both Azure AD (set as App ID URI) and the SAML plugin (set as Entity ID) configuration in Jenkins. So write it down.

gitops model

gitops model

API Permissions

Of course, things wouldn't be proper IAM/LDAP/AD without giving some permissions.

If we want to retrieve group information and other fields, we need to be able to read the Directory information.

gitops model

You find the Directory information via the Microsoft Graph api button.

gitops model

We select Application Permissions and then check Directory.Read.All. We don't need to write.

gitops model

The Permissions have changed, so we require an Administrator account to consent with the new permissions.

gitops model

Update Manifest

As with the permissions, the default Manifest doesn't give us all the information we want.

We want the groups so we can configure RBAC, and thus we have to set the groupMembershipsClaims claim attribute.

gitops model

We change the null to "SecurityGroup". Please consult the Microsoft docs (see reference below) for other options.

We can download, edit, and upload the manifest file. Alternatively, we can edit inline and hit save on top.

gitops model

Retrieve Group Object ID

If we want to assign Azure AD groups to groups or roles in Jenkins' RBAC, we need to use the Object ID's.

Each Group and User has an Object ID, which have a handy Copy this button on the end of the value box!

gitops model

Configure Jenkins

We now get to the point where we configure Jenkins. The SAML plugin is opensource, and thus it's configuration can also be used for Jenkins or CloudBees Jenkins Distribution.

Steps

Here are the steps we perform to configure Azure AD as the Single-Sign-On solution.

Visual Guide

Below is a visual guide with screenshots. Please pay attention to the hints in the screenshots.

  • Red: this is the main thing
  • Orange: this is how we got to the current page/view
  • Blue: while you're in this screen, there might be other things you could do

Configure Security

To go to Jenkins' security configuration, follow this route:

  • login with an Admin user
  • go to the Operations Center
  • Manage Jenkins -> Global Security Configuration
Configure RBAC

The SAML plugin configuration pollutes the screen with fields.

My advice is to enable RBAC first.

If you haven't got any groups/roles yet, I recommend using the Typical Initial Setup from the dropdown. The logged-in user is automatically registered as administrator. So if your Azure AD configuration doesn't work, this user can still manage Jenkins.

gitops model

Important

Make sure you know the credentials of the current admin user.

It will automatically be added to the Administrators group, and it will be your go-to account when you mess up the SAML configuration and you have to reset security.

For how to reset the security configuration, see the For When You Mess Up paragraph.

Configure SAML

Select SAML 2.0 from the Security Realm options.

Here we first supply our Federation Metadata Document content or it's URL.

Each option - document content or URL - has its own Validate ... button, hit it and confirm it says Success.

gitops model

gitops model

Info

You can leave Displayname empty, which gives you the default naming scheme from Azure AD. I think this is ugly, as it amounts to something like ${EMAIL_ADDRESS}_${AD_DOMAIN}_${AZURE_CORP_DOMAIN}. There are other options, I've settled for givenname, as there isn't a fullname by default, and well, I prefer Joost to a long hard to recognize string.

Fields
  • Displayname: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
  • Group: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups
  • Username: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name
  • Email: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress
  • SP Entity ID: the App ID URI you configured in Azure AD (hidden behind Advanced Configuration)

Configure RBAC Groups

Tip

Once Azure AD is configured, and it works, you can configure groups for RBAC just as you're used to.

Both for classic RBAC and Team Masters.

Just make sure you use the Azure AD Object ID's of the groups to map them.

Bonus tip, add every Azure AD group to Browsers, so you can directly map their groups to Team Master roles without problems.

gitops model

gitops model

XML Config

  <useSecurity>true</useSecurity>
  <authorizationStrategy class="nectar.plugins.rbac.strategy.RoleMatrixAuthorizationStrategyImpl"/>
 <securityRealm class="org.jenkinsci.plugins.saml.SamlSecurityRealm" plugin="saml@1.1.2">
    <displayNameAttributeName>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname</displayNameAttributeName>
    <groupsAttributeName>http://schemas.microsoft.com/ws/2008/06/identity/claims/groups</groupsAttributeName>
    <maximumAuthenticationLifetime>86400</maximumAuthenticationLifetime>
    <emailAttributeName>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress</emailAttributeName>
    <usernameCaseConversion>none</usernameCaseConversion>
    <usernameAttributeName>http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name</usernameAttributeName>
    <binding>urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect</binding>
    <advancedConfiguration>
      <forceAuthn>false</forceAuthn>
      <spEntityId>https://cloudbees-core.kearos.net</spEntityId>
    </advancedConfiguration>
    <idpMetadataConfiguration>
      <xml></xml>
      <url>https://login.microsoftonline.com/95b46e09-0307-488b-a6fc-1d2717ba9c49/federationmetadata/2007-06/federationmetadata.xml</url>
      <period>5</period>
    </idpMetadataConfiguration>
  </securityRealm>
  <disableRememberMe>false</disableRememberMe>

Logout URL

Depending on the requirements, you may want to specify a logout url in the SAML configuration to log you completely out of SAML, not just Core.

An example https://login.windows.net/<tenant_id_of_your_app>/oauth2/logout?post_logout_redirect_uri=<logout_URL_of_your_app>/logout

For When You Mess Up

This is the default config for security in CloudBees Core.

This file is in ${JENKINS_HOME}/config.xml, the XML tags we want to look at are quite near the top.

 <useSecurity>true</useSecurity>
  <authorizationStrategy class="hudson.security.FullControlOnceLoggedInAuthorizationStrategy">
    <denyAnonymousReadAccess>true</denyAnonymousReadAccess>
  </authorizationStrategy>
  <securityRealm class="hudson.security.HudsonPrivateSecurityRealm">
    <disableSignup>true</disableSignup>
    <enableCaptcha>false</enableCaptcha>
  </securityRealm>
  <disableRememberMe>false</disableRememberMe>

On CloudBees Core Modern / Kubernetes

To rectify a failed configuration, execute the following steps:

  1. exec into the cjoc-0 container: kubectl exec -ti cjoc-0 -- bash
  2. open config.xml: vi /var/jenkins_home/config.xml
  3. replace conflicting lines with the above snippet
  4. save the changes
  5. exit the container: exit
  6. kill the pod: kubectl delete po cjoc-0

Tip

For removing a whole line, stay in "normal" mode, and press d d (two times the d key). To add the new lines, go into insert mode by pressing the i key. Go back to "normal" mode by pressing the esc key. Then, save and quit, by writing: :wq followed by enter.

References

Info

Currently, there is a limitation which requires you to use the Object ID's which make searching groups and people less than ideal. When the Alternative Azure AD Plugin is approved this may provide a more satisfactory solution.


Last update: 2019-09-28 23:00:29