Saturday, 27 June 2015

IBM Business Process Manager and Desktop SSO via Kerberos and SPNEGO

Context

This comes on the back of a similar article describing how one can configure IBM Operational Decision Manager (ODM) 8.6 to work with Microsoft Active Directory 2008, and deliver desktop Single Sign-On for Windows users.

In this scenario, ODM has been "replaced" by IBM BPM Advanced 8.5.5.0 on IBM WebSphere Application Server (WAS) 8.5.5.2.

Again, the objective is to configure WAS to use Active Directory 2008 for identity management, authentication and authorisation ( access control ). In addition, Kerberos / SPNEGO will be configured in AD and in WAS, in order to allow Windows desktop users to automatically access BPM functionality without being challenged for credentials ( using their existing Windows log in ).

This article is broken into sections, and requires each section to be completed in order. In addition, it is assumed that AD has already been configured, and that the relevant users and groups have been created.

The following is intended to provide an example of the typical users and groups that one might require: -

WAS > AD Bind User

dn: CN=ldapbind,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com

WAS Administration User

dn: CN=WebSphere Admin,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com

WAS Administration Group

dn: CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com
member: CN=WebSphere Admin,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com

BPM Administration Group

dn: CN=BPMAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com
member: CN=Administrator,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com

BPM Authors Group

dn: CN=BPMAuthors,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com
member: CN=Administrator,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com

BPM Users Group

dn: CN=BPMUsers,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com
member: CN=Administrator,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com

Pre-Requisites

  • IBM BPM Advanced 8.5.5.0 installed on WebSphere Application Server Network Deployment 8.5.5.2, with IBM HTTP Server and IBM WebSphere Plugin.
  • IHS/Plugin federated into WAS cell
  • IHS configured for SSL
  • WAS Virtual Host for IHS SSL port added ( 8443 in this case )
  • IHS-hosted SSL certificate in WAS cell-default trust store

WAS Tasks

Start WSAdmin

/opt/IBM/WebSphere/AppServer/profiles/Dmgr01/bin/wsadmin.sh -lang jython

Create LDAP Repository

AdminTask.createIdMgrLDAPRepository('[-default true -id ad2008.uk.ibm.com -adapterClassName com.ibm.ws.wim.adapter.ldap.LdapAdapter -ldapServerType AD -sslConfiguration -certificateMapMode exactdn -supportChangeLog none -certificateFilter -loginProperties uid]')

Add AD Server

AdminTask.addIdMgrLDAPServer('[-id ad2008.uk.ibm.com -host ad2008.uk.ibm.com -bindDN CN=ldapbind,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com -bindPassword Qk525mtp -referal ignore -sslEnabled false -ldapServerType AD -sslConfiguration -certificateMapMode exactdn -certificateFilter -authentication simple -port 389]')

Add Base Entry

AdminTask.addIdMgrRepositoryBaseEntry('[-id ad2008.uk.ibm.com -name CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com -nameInRepository CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com]')

Add Realm Base Entry

AdminTask.addIdMgrRealmBaseEntry('[-name defaultWIMFileBasedRealm -baseEntry CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com]')

Add User Object Classes and Search Base

AdminTask.updateIdMgrLDAPEntityType('[-id ad2008.uk.ibm.com -name PersonAccount -objectClasses user;organizationalPerson;person -searchBases CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com -searchFilter (ObjectCategory=User)]')

Add Group Object Class and Search Base

AdminTask.updateIdMgrLDAPEntityType('[-id ad2008.uk.ibm.com -name Group -objectClasses group -searchBases CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com -searchFilter (ObjectCategory=Group)]')

Enable Allow Operation If Repository Down

AdminTask.updateIdMgrRealm('[-name defaultWIMFileBasedRealm -allowOperationIfReposDown true]')

Add AD Group ( ) into Admin Roles

AdminTask.mapGroupsToAdminRole('[-roleName adminsecuritymanager -accessids [group:defaultWIMFileBasedRealm/CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ] -groupids [WebSphereAdmins@defaultWIMFileBasedRealm ]]')
AdminTask.mapGroupsToAdminRole('[-roleName administrator -accessids [group:defaultWIMFileBasedRealm/CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ] -groupids [WebSphereAdmins@defaultWIMFileBasedRealm ]]')
AdminTask.mapGroupsToAuditRole('[-roleName auditor -accessids [group:defaultWIMFileBasedRealm/CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ] -groupids [WebSphereAdmins@defaultWIMFileBasedRealm ]]')
AdminTask.mapGroupsToAdminRole('[-roleName configurator -accessids [group:defaultWIMFileBasedRealm/CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ] -groupids [WebSphereAdmins@defaultWIMFileBasedRealm ]]')
AdminTask.mapGroupsToAdminRole('[-roleName deployer -accessids [group:defaultWIMFileBasedRealm/CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ] -groupids [WebSphereAdmins@defaultWIMFileBasedRealm ]]')
AdminTask.mapGroupsToAdminRole('[-roleName iscadmins -accessids [group:defaultWIMFileBasedRealm/CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ] -groupids [WebSphereAdmins@defaultWIMFileBasedRealm ]]')
AdminTask.mapGroupsToAdminRole('[-roleName monitor -accessids [group:defaultWIMFileBasedRealm/CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ] -groupids [WebSphereAdmins@defaultWIMFileBasedRealm ]]')
AdminTask.mapGroupsToAdminRole('[-roleName operator -accessids [group:defaultWIMFileBasedRealm/CN=WebSphereAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ] -groupids [WebSphereAdmins@defaultWIMFileBasedRealm ]]')

Save and Sync

AdminConfig.save()
AdminNodeManagement.syncActiveNodes()
quit

AD Tasks

Create Service Principal Name

setspn -a HTTP/bpm855.uk.ibm.com ldapbind

Validate SPN

setspn -l ldapbind

Create Kerberos Keytab

ktpass -out bpm855.keytab -princ HTTP/ bpm855.uk.ibm.com@AD2008 -mapUser AD2008\ldapbind -mapOp set -pass Qk525mtp -ptype KRB5_NT_PRINCIPAL

WAS Tasks

Validate Kerberos Keytab

ktutil

ktutil: rkt bpm855.keytab
ktutil: list

slot KVNO Principal
---- ---- ---------------------------------------------------------------------
   1    3            HTTP/bpm855.uk.ibm.com@AD2008

ktutil: quit

/opt/IBM/WebSphere/AppServer/java/jre/bin/java com.ibm.security.krb5.internal.tools.Klist -e -k /home/wasadmin/bpm855.keytab

Key table: /home/wasadmin/bpm855.keytab
Number of entries: 1

[1] principal: HTTP/bpm855.uk.ibm.com@AD2008
KVNO: 3

Encryption type: RC4 with HMAC

Create Kerberos Configuration File

/opt/IBM/WebSphere/AppServer/profiles/Dmgr01/bin/wsadmin.sh -lang jython

AdminTask.createKrbConfigFile("[-krbPath /opt/IBM/WebSphere/AppServer/java/jre/lib/security/krb5.conf -realm UK.IBM.COM -kdcHost ad2008.uk.ibm.com.com -dns uk.ibm.com -keytabPath /home/wasadmin/bpm855.keytab -encryption des3-cbc-sha1]")

'/opt/IBM/WebSphere/AppServer/java/jre/lib/security/krb5.conf has been created.'

AdminConfig.save()
AdminNodeManagement.syncActiveNodes()
quit

Validate

cat /opt/IBM/WebSphere/AppServer/java/jre/lib/security/krb5.conf

[libdefaults]
   default_realm = UK.IBM.COM
   default_keytab_name = FILE:/home/
wasadmin/bpm855.keytab
   default_tkt_enctypes = des3-cbc-sha1
   default_tgs_enctypes = des3-cbc-sha1
   forwardable  = true
   renewable  = true
   noaddresses = true
   clockskew  = 300
[realms]
   UK.IBM.COM = {
     kdc = ad2008.uk.ibm.com.com:88
     default_domain = uk.ibm.com
   }
[domain_realm]

Add SPNEGO Configuration

/opt/IBM/WebSphere/AppServer/profiles/Dmgr01/bin/wsadmin.sh -lang jython
AdminTask.addSpnegoFilter('[-hostName bpm855.uk.ibm.com -krb5Realm AD2008 -filterCriteria -filterClass -spnegoNotSupportedPage -ntlmTokenReceivedPage -trimUserName true -enabledGssCredDelegate false]')
AdminTask.configureSpnego('[-enabled true -dynamicReload true -allowAppAuthMethodFallback true -krb5Config /opt/IBM/WebSphere/AppServer/java/jre/lib/security/krb5.conf -krb5Keytab /home/wasadmin/bpm855.keytab]')
AdminTask.setAdminActiveSecuritySettings('[-customProperties ["com.ibm.websphere.security.krb.canonical_host=true"] ]')
AdminConfig.save()
AdminNodeManagement.syncActiveNodes()
quit

Create Fallback Login Page - /opt/IBM/HTTPServer/htdocs/NoSpnegoRedirect.html

This page is used when (a) one uses a browser that is not configured for SPNEGO e.g. Chrome or Safari etc. and (b) when one chooses NOT to invoke SSO by adding ?noSPNEGO to the URL

<!DOCTYPE HTML PUBLIC "-//W3C/DTD HTML 4.0 Transitional//EN">
<META HTTP-EQUIV="Content-Type" CONTENT="text/html">
<!--
Notes:
- This file should be served from an unprotected website. Alternatively, it can be loaded from the WebSphere Application Server file system.
- Any imbedded graphics/javascript/css must be loaded from an unprotected website.
- This file is loaded after WebSphere Application Server is initialized. If changes to this file are necessary, restart WebSphere Application Server.
- This file is returned whenever the SPNEGO TAI receives an NTLM token for any application in the cell. In other words, this file is generic for all applications. However, by using the  document.location Javascipt,
- we can get the original URL, and redirect to that original URL with the "?noSPNEGO" text added - thus forcing the standard application userid/password challenge.
-->
<html>
<script language="javascript">
var origUrl=""+document.location;
   if (origUrl.indexOf("noSPNEGO")<0) {
if (origUrl.indexOf('?')>=0) origUrl+="&noSPNEGO";
else origUrl+="?noSPNEGO";
}
function redirTimer() {
self.setTimeout("self.location.href=origUrl;",0);
}
</script>

<META HTTP-EQUIV = "Pragma" CONTENT="no-cache">
<script language="javascript">
document.write("<title> Redirect to "+origUrl+ " </title>");
</script>
<head>
</head>
<body onLoad="redirTimer()"/>
</html>

Add Fallback Login Page to WAS

This also updates the SPNEGO filters to disable SSO between Process Center and Process Server - see SPNEGO authentication might cause communication issues between the Process Server and the Process Center for IBM Business Process Manager (BPM)

/opt/IBM/WebSphere/AppServer/profiles/Dmgr01/bin/wsadmin.sh -lang jython
AdminTask.modifySpnegoFilter('[-hostName bpm855.uk.ibm.com -krb5Realm AD2008 -filterCriteria request-url!=ProcessCenterInternal;request-url!=ProcessServerInternal;request-url^=ProcessCenter|ProcessAdmin|portal|ProcessPortal|teamworks|PerformanceAdmin;request-url!=noSPNEGO; -filterClass -spnegoNotSupportedPage https://bpm855.uk.ibm.com:8443/NoSpnegoRedirect.html -ntlmTokenReceivedPage https://bpm855.uk.ibm.com:8443/NoSpnegoRedirect.html -trimUserName true -enabledGssCredDelegate false]')
AdminConfig.save()
AdminNodeManagement.syncActiveNodes()
quit

Restart Deployment Environment

/opt/IBM/WebSphere/AppServer/bin/BPMConfig.sh -stop -profile Dmgr01 -de De1

/opt/IBM/WebSphere/AppServer/bin/BPMConfig.sh -start -profile Dmgr01 -de De1

Windows Desktop Tasks ( IE )

Enable Integrated Windows Authentication (IWA), if not already enabled: -

 

Add https://bpm855.uk.ibm.com to Local Intranet Trusted Zone: -




Restart IE and access Process Center URL: -


SSO should now work i.e. one should be logged into PC as the Windows user - Administrator: -


The same should work for Process Admin: -


and Process Portal: -


By default, however, SSO for Performance Admin: -


will not work, purely because the only user authorised to access Performance Admin is deAdmin.

This means that the login page will be presented, with a corresponding message in SystemOut.log ( for the SupportCluster ): -

[14/11/14 10:17:18:401 GMT] 00000143 WebCollaborat A   SECJ0129E: Authorization failed for user Administrator:defaultWIMFileBasedRealm while invoking GET on default_host:/PerformanceAdmin/console/Welcome.do, Authorization failed, Not granted any of the required roles: twuser

If needed, this could be mitigated by adding, for example, BPMAdmins into the twuser role for the Performance Admin application: -

/opt/IBM/WebSphere/AppServer/profiles/Dmgr01/bin/wsadmin.sh -lang jython
AdminApp.edit('IBM_BPM_PerformanceDW_SupCluster', '[ -MapRolesToUsers [[ twuser AppDeploymentOption.No AppDeploymentOption.No deAdmin BPMAdmins AppDeploymentOption.No " " group:defaultWIMFileBasedRealm/CN=BPMAdmins,CN=Users,DC=ad2008,DC=uk,DC=ibm,DC=com ]]]' )
AdminConfig.save()
AdminNodeManagement.syncActiveNodes()
quit

However, this requires insight from the business, as the security requirements for the Performance Admin console may differ to those for Process Center, Process Portal, Process Admin etc.

Optional and Additional Steps

BPM internal groups can be updated using Process Admin in order to enforce specific roles when using SSO: -

Internal BPM Group AD Group

tw_authors BPMAuthors
tw_admins BPMAdmins
tw_allusers BPMUsers

Success in Pictures

Process Center


Process Portal


Process Admin


Performance Admin


References






2 comments:

Max said...

Hi,

why are you using the host name instead of domain name in "HTTP/bpm855.uk.ibm.com@AD2008"?
e.g I will use a command-line as shown below , Am I correct?
BTW , I have created computer name for Kerberos in Active Directory Users and computers and A record in DNS Server. please clarify me

ktpass -out bpm855.keytab -princ HTTP/wasnd.corp.contoso.com@CORP.CONTOSO.COM -mapUser ldapbind -mapOp set -pass Qk525mtp -ptype KRB5_NT_PRINCIPAL

Secondly , I am assuming there is a typo within kdchost parameter.

-kdcHost ad2008.uk.ibm.com.com

thanks

Dave Hay said...

Hi

Thanks for the comments.

In the first instance, theSPN and keytab is being generated for a Service, rather than a host. I've merely used bpm855.uk.ibm.com as an example. In the real world, this'd likely be a load-balanced service, perhaps hosted on a real load balancer such as a Big IP F5 appliance or via a virtual host name in DNS ( one host name balancing requests to multiple real hosts, perhaps via round-robin ).

Take a look at the ktpass documentation, such as: -

https://technet.microsoft.com/en-us/library/cc753771.aspx

http://www-01.ibm.com/support/knowledgecenter/SSAW57_8.5.5/com.ibm.websphere.nd.doc/ae/tsec_kerb_create_spn.html?cp=SSAW57_8.5.5%2F1-3-0-22-0-0&lang=en

etc.

With regard to your second point, yes, that IS a typo :-) Thanks for noticing :-)

Cheers, Dave

Note to self - use kubectl to query images in a pod or deployment

In both cases, we use JSON ... For a deployment, we can do this: - kubectl get deployment foobar --namespace snafu --output jsonpath="{...