SiteMinder Policy conversion to OpenAM XACML

In this article I discuss migrating SiteMinder policies to OpenAM. I have laid out an approach and framework to make the conversion possible using XML parsing, XML codifying and custom metadata that is necessary to resolve embedded repository externalities in the SiteMinder policy definition. I have also written a Java-based program that uses the methodology discussed in this article to parse through the SiteMinder policy and resolve each policy construct to an OpenAM equivalent policy object. The program codifies the XACML output step-by-step and on completion, one is able to import the XACML policy set into OpenAM via the policy editor.

There are going to be some complications in your situation such as when converting whitelisted resource URI – that SiteMinder does not ‘trap’ in the policy definition- you will need to know which URI are not in your SM policy extract and allowed by default, and then go about creating or adding the same URI in a new or ‘converted’ OpenAM policy. You would then need to whitelist those URI by explicitly allowing access in OpenAM.

I begin by describing the general layout of an XPS domain export at a high level, and how different policy constructs in a SiteMinder policy map over to OpenAM.

Survey of SiteMinder Policy Objects

While there is not a one-to-one mapping for every policy construct, there is a logical mapping that is useful to achieve a first pass on the conversion. Some of the complications are elaborated on below.

CA.SM::Domain -> OpenAM Policy Set Definition

The CA.SM::Domain object is the parent object to several domain-specific properties such as Mode, Name and UserDirectoriesLink references. Nested directly under the Domain object are CA.SM::Realm,  CA.SM::Policy and CA.SM::Response objects.

CA.SM::Realm -> OpenAM Policy Resources

The Realm object includes properties that describe the AgentGroupLink and AuthScheme settings, session properties such as IdleTimeout, and among other things, the ResourceFilter that is the protected resource URI. Realm also contains a nested object, called the CA.SM::Rule with an associated XID that describes the Actions available for the ResourceFilter- such as GET, PUT and POST- and properties that describe regular expression matching, time restrictions, resource pattern and IsEnabled among other things.

CA.SM::Response -> OpenAM Response Attributes

Response object is a container for one or more name-value pairs, or ‘response attributes’ expected by the agent. These can be of type Web agent responses or RADIUS responses. This conversion article and the Java program are limited to handling only the Web agent responses currently.

The Response object has an associated XID, and includes properties that describe the authorization conditions when the response is applicable- such as AccessAccept and AccessChallenge- and properties for AgentTypeLink and Name.

CA.SM::ResponseAttr

Response also nests CA.SM::ResponseAttr objects, each with a unique XID, that each have properties for AgentTypeAttrLink- pointing to ReferenceObjects such as “WebAgent-HTTP-Header-Variable” indicating the means of transport for the response attributs- and also the Value of the response codified in the form of display-name=<%userattr=”profile-attribute-name”%>. Here it is assumed that the value is sourced from a user attribute, which is mostly the case, although several types of ResponseAttrs are possible, including user attribute as already mentioned, DN Attribute, Static values, Session Variable, etc.

CA.SM::Policy -> OpenAM Policy Definition

Nested under the Domain object, and at peer level to the Realm and Response objects is the CA.SM::Policy object that serves to tie together protected resource URI to the corresponding user audience, rules including actions, response objects and optionally, IP address restrictions and time restrictions for those URI.

CA.SM::PolicyLink

The Policy object container has one or more CA.SM::PolicyLink objects that can be thought of as associations between the protected resources and the responses configured for each of them. The PolicyLink objects each have CA.SM::ResponseLink and CA.SM::RuleLink properties.

CA.SM::ResponseLink and CA.SM::RuleLink

The ResponseLink is a pointer to the Response object definition, and the RuleLink is a pointer to the Rule definition stored inside a CA.SM::Realm object. When invoked for a specific Realm, the policy enforces the Rule Actions as well as the Response attributes in case the policy evaluation is successful.

CA.SM::UserPolicy

The Policy object also contains one or more CA.SM::UserPolicy objects that can be thought of as audience restriction conditions. The UserPolicy object has properties defining the FilterPath, which is a SQL query but one that could be used to locate a set of users this policy applies to. Another property is the UserDirectoryLink that is a pointer to the external repository that contains the user profile data, and specifically stores the XID of the ReferenceObject by the name CA.SM::UserDirectory.

References

Besides Domain objects, there are also reference objects at a peer level to Domain. The Reference object tree encapsulates all external information that the policy references.

CA.SM::UserDirectory

The user repository information is stored under the CA.SM::UserDirectory ReferenceObject that includes a NameSpace attribute- such as “ODBC:”- and Server name. As mentioned previously the UserPolicy object stores a reference to the UserDirectory object using a UserDirectoryLink.

The program relies on these user directory references to be resolved using a metadata container in OpenDJ.

CA.SM::AgentGroup

The AgentGroup object refers to the SiteMinder agent configurations that all protect the same resources. The attribute AgentTypeLink contains a value that is referenced from CA.SM::Response objects using the AgentTypeLink property tying the web agent to that particular response object. There could be one or more Agent Groups.

CA.SM::AgentTypeAttr

One or more of these Reference objects define in what form the agent expects the response objects to be returned. Two currently supported, and commonly used, values include “WebAgent-HTTP-Header-Variable” and “WebAgent-HTTP-Cookie-Variable”. These are available for use in accept or reject responses only in SiteMinder.

Some other Reference objects include CA.SM::AgentType, which describes the SM agent- basically a Web Agent. Another is the CA.SM::AuthScheme which includes details about the form of authentication such as Forms-based, Basic auth or API.

Conversion to OpenAM

Converting CA.SM::Domain and CA.SM::Realm objects

Simply parse out these objects from the SiteMinder policy extract and create OpenAM policy set XACML definitions.

A code sample to establish the proper order and parity between the XACML elements is shown here:

        Element target = doc.createElementNS("ns2", "ns2:Target");
 	Element anyOf_subject = getAnyOfSubjectTree(doc, xmlMap);
 	target.appendChild(anyOf_subject);

 	Element anyOf_resource = getAnyOfResourceTree(doc, xmlMap, resourceUri);
 	target.appendChild(anyOf_resource);
 		
  	Element anyOf_application = getAnyOfApplicationTree(doc, xmlMap);
       	target.appendChild(anyOf_application);
       	
       	Element anyOf_action = getAnyOfActionTree(doc, xmlMap, actions);
       	target.appendChild(anyOf_action);

A code sample for creating the Resource URI in XACML format is shown below:

private static Element getAnyOfResourceTree(Document doc, Map<String, String> xmlMap, List resourceUri) {
// many AnyOf elements to define subject, resources, actions, etc
  	Element anyOf = doc.createElementNS("ns2", "ns2:AnyOf");
  	for(String url : resourceUri) {
		Element allOf = doc.createElementNS("ns2", "ns2:AllOf");
		Element Match = doc.createElementNS("ns2", "ns2:Match");
		Match.setAttribute("MatchId", "urn:sun:opensso:entitlement:resource-match:application:"+xmlMap.get("PolicyId"));
	       	Element AttributeValue = doc.createElementNS("ns2", "ns2:AttributeValue");
                AttributeValue.setAttribute("DataType", "http://www.w3.org/2001/XMLSchema#string");
                AttributeValue.setTextContent("*://*:*" + url);
   	        Match.appendChild(AttributeValue);
	       	Element AttributeDesignator = doc.createElementNS("ns2", "ns2:AttributeDesignator");
	       	AttributeDesignator.setAttribute("Category", "urn:oasis:names:tc:xacml:3.0:attribute-category:resource");
	       	AttributeDesignator.setAttribute("AttributeId", "urn:oasis:names:tc:xacml:1.0:resource:resource-id");
	       	AttributeDesignator.setAttribute("MustBePresent", "true");
	       	AttributeDesignator.setAttribute("DataType", "http://www.w3.org/2001/XMLSchema#string");
	       	Match.appendChild(AttributeDesignator);
	       	allOf.appendChild(Match);
	       	anyOf.appendChild(allOf);
  	}
	return anyOf;
}

Converting the CA.SM::Rule.Actions objects

Here the challenge is to convert the ResourceFilters into ResourceURI objects in the XACML definition, and then add the relevant actions to those resource URI as defined in the CA.SM::Realm object definition. A sample method that adds basic actions to a policy is shown here:

private static Element getAnyOfActionTree(Document doc, Map<String, String> xmlMap, List actions) {
	// many AnyOf elements to define subject, resources, actions, etc
  		Element anyOf = doc.createElementNS("ns2", "ns2:AnyOf");
  		for(String action : actions) {
      		Element allOf = doc.createElementNS("ns2", "ns2:AllOf");
  		Element Match = doc.createElementNS("ns2", "ns2:Match");
  		Match.setAttribute("MatchId", "urn:sun:opensso:entitlement:action-match:application:"+xmlMap.get("PolicyId"));
	       	Element AttributeValue = doc.createElementNS("ns2", "ns2:AttributeValue");
	       	AttributeValue.setAttribute("DataType", "http://www.w3.org/2001/XMLSchema#string");
	       	AttributeValue.setTextContent(action);
		   Match.appendChild(AttributeValue);
	       	Element AttributeDesignator = doc.createElementNS("ns2", "ns2:AttributeDesignator");
	       	AttributeDesignator.setAttribute("Category", "urn:oasis:names:tc:xacml:3.0:attribute-category:action");
	       	AttributeDesignator.setAttribute("AttributeId", "urn:oasis:names:tc:xacml:1.0:action:action-id");
	       	AttributeDesignator.setAttribute("MustBePresent", "true");
	       	AttributeDesignator.setAttribute("DataType", "http://www.w3.org/2001/XMLSchema#string");
	       	Match.appendChild(AttributeDesignator);
	       	allOf.appendChild(Match);       	
	       	anyOf.appendChild(allOf);
  	}
  	return anyOf;
   }

Converting Policy bindings for CA.SM::Real,  CA.SM::Response and CA.SM::UserPolicy objects

This portion is the most complex in the conversion because linkages have to be parsed out of the SiteMinder policy extract and rendered as separate OpenAM policies in XACML format. In order to convert a CA.SM::Policy object the program needs to follow the following algorithm at the very at least and in order:

  1. Establish the linkages between the CA.SM::Realm objects and the CA.SM::Response objects using the PolicyLink binder object
  2. Resolve the Response object, dynamic key-value pairs, by either directly reading the data from an external repository, or converting the references attributes to LDAP specific attributes
  3. Resolve the Subject Restrictions manifest in the PolicyLink.UserPolicy by converting the SQL Query to an LDAP search filter
  4. Create one OpenAM policy under the previously established Policy Set per Realm-Response-UserPolicy linkage

These steps are necessary in order to preserve the linkage of specific resource URI being accessible over the policy decision and returning specific response attributes.

Parsing out the bindings between CA.SM::Realm and CA.SM::Response objects

Since not all CA.SM::Realm objects in the SiteMinder policy extract refer to all the CA.SM::Response objects it becomes necessary to collect those objects that are bound together and dispatch them into one OpenAM policy. This is because OpenAM ties together a group of protected resource URI to a group of subject conditions, environment conditions and response attributes.

Resolving the Response object into static or dynamic OpenAM Response Attributes

A design decision here could be that the response attributes will be pulled from a user repository such as OpenDJ, making the CA.SM::ResponseAttr.Value definitions very easy to resolve. After parsing the definitions that usually are of the form:

CL_Header=<%userattr="<%userattr="CL_Cookie_Value"%>|UID=<%userattr="DEF_PROFILE_ID"%>|State=<%userattr="ST"%>|City=<%userattr="ADDR_CITY"%>|AddressLine1=<%userattr="ADDR1"%>|AddressLine2=<%userattr="ADDR2"%>|CompanyName=<%userattr="COMPANY"%>

One could construct the response objects one by one, with the display attribute (left of the “=” sign) as key and user profile attribute within quotes above, as the value. Simplistic string split and parsing techniques could be used to achieve this. The mapping of user profile attributes shown here could also be stored as key-value pairs in a metadata container in OpenDJ:

 

meta

Here, the connection information is stored as an LDAP url in description, admin username in sn and password (hidden) in givenName. The mapping of the user attributes is stored in cn. Using this information the program resolves the key-value pairs from the source repository to that of the target repository schema and the resulting key-value pairs are codified as OpenAM Response objects into XACML, as shown:

urn:sun:opensso:entitlement:json-resource-attribute:com.sun.identity.entitlement.UserAttributes:<attr-name>

Resolve the Subject Restrictions manifest in the PolicyLink.UserPolicy

Converting subject conditions derived from CA.SM::UserPolicy objects such as this one:

userpolicy

..would involve the same framework presented above, except this time we will create an LDAP search filter from the SQL Query- again assuming we are seeking data from an LDAP repository- to ensure the policy is only fired when the subject condition is satisfied.

The program can also provide support for directly retrieving user profile attributes – either for Subject Restrictions presented above in the form of LDAP filters, or for dynamically creating the Response key-value pairs in XACML. The metadata can have connection information stored as shown above that could be used to achieve this external lookup.

 

A Framework for Dynamic Roles and Assignments in OpenIDM

This solution article demonstrates how to add and delete users to ldap groups, statically and also dynamically using custom mappings in reconciliations. I attempt to present a framework in OpenIDM that can be used for setting up a simple entitlement framework where you can automatically attach roles to assignments, making RBAC easier to implement.
This blog article uses sample2b and is specifically referring to the following doc link:
https://backstage.forgerock.com/#!/docs/openidm/4/samples-guide%23provrole-add-assignments
Let us begin by laying the groundwork first, and describe how to create roles and assignment manually in OpenIDM. This solution article assumes you have gone through the doc-link above and are familiar with sample2b.

Static Assignments

The key idea is to create an assignment, and add the group you want assigned under “Attributes” as shown below:
Inline image 1
And then of course, “attach” this assignment to the Provisioning Role you reconciled from DJ:
Inline image 2
Now, it is a matter of assigning the Provisioning Role to the user in order to have the LDAP group “cn=impersonation” assigned to the user in OpenDJ.
Inline image 3
DJ’s ldapsearch will validate the correct group was assigned:

./ldapsearch –port 1389 –hostname localhost –baseDN “dc=forgerock,dc=com” –bindDN “cn=directory manager” –bindPassword xxx –searchscope sub “(uid=user.10)” dn uid isMemberOf

dn: uid=user.10,ou=People,dc=forgerock,dc=com

uid: user.10

isMemberOf: cn=impersonation,ou=groups,dc=forgerock,dc=com

Once you remove the role, ldapsearch will validate that the group was deleted in DJ:

Inline image 4

./ldapsearch –port 1389 –hostname localhost –baseDN “dc=forgerock,dc=com” –bindDN “cn=directory manager” –bindPassword xxx –searchscope sub “(uid=user.10)” dn uid isMemberOf

dn: uid=user.10,ou=People,dc=forgerock,dc=com

uid: user.10

 

Note that, each one of these IDM UI steps can be performed over REST as well.

Dynamic Assignments

Creating assignments dynamically from incoming LDAP groups can also be performed by setting “managed/assignment” and “managed/role” as Recon targets with the help of some scripting involved in the attribute grid.
Begin by creating the following two mappings:
system/ldap/group to managed/assignment
Screen Shot 2016-05-25 at 5.15.43 PM
and, system/ldap/group to managed/role
Screen Shot 2016-05-25 at 5.17.15 PM
The idea here is to automatically create two managed entities from the LDAP Groups container in OpenDJ.
The first managed entity (“managed/role”) is created to hold the named LDAP group objects – deemed Provisioning Roles – in our use case. These LDAP groups you want the users to be automatically added to (or provisioned to in OpenDJ) whenever “same-named” provisioning roles are assigned to a user. These “same-named” provisioning roles happen to be attached to “same-named” assignment objects! (magically!.. not quite, but via transform-scripting as shown below).
The second managed entity (managed/assignment) is created to hold the “same-named” assignment object that you will setup in such a way that it references (internally) the “same-named” provisioning role!
This will become clearer, read on.

Mapping called sourceLdapGroup_managedRole

Screen Shot 2016-05-25 at 5.29.05 PM
This mapping is simple and aims to create “named” provisioning roles inside OpenIDM from the LDAP group objects in OpenDJ. Cannot get simpler than that in this use case- but keep your seat belts fastened, and read on!

 

Side bar for the advanced OpenIDM user: Under reconciliation behavior policies configuration, you want to set Missing condition to Unlink in order to “reset the state” if you will, in the case where you delete a provisioning role accidentally in OpenIDM, but want the next LDAP recon on managed/role to fix it. Just remember to run recon twice!

Mapping called sourceLdapGroup_managedAssignment

Screen Shot 2016-05-25 at 5.20.52 PM

The picture above shows which attributes to map for this particular mapping definition.

For the /attributes map, use the following transformation script:

([{assignmentOperation:'mergeWithTarget',unassignmentOperation:'removeFromTarget',name: 'ldapGroups',value: [ source.dn ]}])

This transformation script sets up the incoming group object as an OpenIDM assignment and also sets up the value of the “ldapGroups” attribute to the DN of the incoming group object.

For /roles, use this one:

([{_ref: 'managed/role/'+( openidm.query('managed/role',{'_queryFilter':'/name eq "' + source.cn + '"'}).result[0]._id)}])
This script queries the managed/role container in OpenIDM for a “named” provisioning role whose CN happens to equal the CN of the incoming group object. This assumes that you reconciled the managed/role objects first- and this is the only dependency for this use case. You cannot really search for a provisioning role’s CN value before you reconcile it from LDAP. After retrieving the correct role object, the script sets the _ref property of the assignment to that particular provisioning role. This is what you would do if you were manually “attaching” a provisioning role to an assignment as shown in the Static Assignments section above.

Demo

Now it is a matter of running reconciliation on sourceLdapGroup_managedRole first, followed by running a reconciliation on sourceLdapGroup_managedAssignment. You should see roles such as:

Screen Shot 2016-05-25 at 5.38.38 PM

And you should see assignments as well- these are basically “named” after the LDAP group objects that have an ldapGroup attribute setup and also an “attachment” setup to a provisioning role:

Screen Shot 2016-05-25 at 5.40.17 PM

 

For example, lets look at the impersonation assignment in detail.

This picture shows the mapping for this assignment object, and the description reconciled from the OpenDJ groups org unit.

 

Screen Shot 2016-05-25 at 5.40.59 PM

 

The picture below shows how the DN of the incoming LDAP group object was mapped to an attribute called “ldapGroups”.

Screen Shot 2016-05-25 at 5.41.05 PM

 

The picture below shows the provisioning role, with the same name of course, that is “attached” to this assignment object.

Screen Shot 2016-05-25 at 5.41.16 PM

 

Now we have an “entitlement” framework for automatically creating assignment and role objects in OpenIDM using single or multiple “source” LDAP group containers, and then attaching these provisioning role objects to assignments. We have simply demonstrated a one-provisioning-role to one-assignment mapping in this use case, but far more complex mappings such as many-to-many or many-to-one are possible. This framework can serve as the foundation for an RBAC type scenario in your deployments! Good luck.

 

 

 

 

Stream application logs to FireEye TAP using rSyslog File Monitoring

Introduction to FireEye TAP

The FireEye Threat Analytics Platform is a cloud-based solution that enables security teams to identify and effectively respond to cyber threats by layering enterprise-generated event data with real-time threat intelligence from FireEye. The platform increases the overall visibility into the threat landscape by leveraging the FireEye Threat Prevention Platforms’ rich insights into threat actor profiles and behavior. More details can be found here:

FireEye Threat Analytics Platform

Use Cases

Addressing a business need is the concept of “Identity Explorer”, using which administrators and case analysts can review the identity related incidents from the enterprise. The ForgeRock-FireEye TAP based solution will help heighten the sense of security, especially one related to BYOD, such as new mobile device registrations.

 

A sample case for detecting fraudulent device registrations is documented here. This is a typical use case wherein a user registers a new device or logs in with the new device from an unknown location. This is deemed a fraudulent login. The key to correctly detecting fraud in this case is knowing that the new location is not one the user would normally login from.

Sample rSyslog Configuration

$ModLoad imfile
$InputFilePollInterval 10
$PrivDropToGroup adm
$WorkDirectory /var/spool/rsyslog

$InputFileName /home/ec2-user/openam12/openam/debug/Authentication
$InputFileTag debugAuth:
$InputFileStateFile stat-debugAuth12-access #this must be unique for each file being polled
$InputFileSeverity info
$InputFilePersistStateInterval 20000
$InputRunFileMonitor

$InputFileName /home/ec2-user/openam12/openam/log/amSSO.access
$InputFileTag amSSO:
$InputFileStateFile stat-amSSO12-access #this must be unique for each file being polled
$InputFileSeverity info
$InputFilePersistStateInterval 20000
$InputRunFileMonitor

$InputFileName /opt/demo/tomcat7b/bin/access.log
$InputFileTag tomcat7baccess:
$InputFileStateFile stat-tomcat7baccess12-access #this must be unique for each file being polled
$InputFileSeverity info
$InputFilePersistStateInterval 20000
$InputRunFileMonitor
# Add a tag for file events
$template TAPFormatFile,"<%pri%>%protocol-version% %app-name% %procid% %msgid% %msg%n"

# Send to TAP then discard
if $programname == 'debugAuth' then @@127.0.0.1:516;TAPFormatFile
if $programname == 'amSSO' then @@127.0.0.1:516;TAPFormatFile
if $programname == 'tomcat7baccess' then @@127.0.0.1:516;TAPFormatFile

OpenAM Debug Logging

Enable debug logging for Category: Authentication in /openam/Debug.jsp

FireEye Communications Broker Setup

You would setup a proprietary software on your unix server that listens on TCP:516 and routes incoming data to the FireEye TAP servers.

Viewing Parsed Log Messages in TAP

Search for class:forgerock (this would be the name of your integration as agreed upon with FireEye), and for program:amauth. Other examples are program:amsso and program:ampolicy.

If parsing is working correctly, the TAP administration would see messages corresponding to the program name show up. In this screen shot the client’s IP is hidden. The next step is to create ALERTS that key off on certain field values parsed out of the logs.

Here is a sample alert for a user logging on from an unknown location:

 

The following screenshot shows a list of locations the user, User.120 has signed on from over the past month.

 

The logins from Tokyo, Frankfurt and Singapore could be deemed anomalous, and corresponding logs added to a new incident to investigate this behavior.

Here is the device information shown in TAP:

Here I show how logs from TAP can be added to a previously created, or new incident.

The analyst assigned to service the alert, and incident would need to login to TAP and investigate using session parameters such as timestamp, device name, OpenAM server name and possibly create a request to revoke or temporarily disable access for User.120 in OpenAM.

Modeling user behavior using OpenAM and Guardian Analytics

Guardian’s FraudMAP Access

A brief overview of Guardian’s flagship analytics engine is in order. A range of methods from malware to social engineering to phishing schemes plus combinations of these can be used by cyber criminals to defeat authentication and illegally access accounts. FraudMAP Access is able to detect the fraudster’s unexpected or suspicious activity when it occurs, as compared to the victim’s typical login behavior. FraudMAP Access models the normal behavior of every user or account holder, building and continually updating individual profiles against which all subsequent activity is compared to look for unusual activity. Powered by Guardian Analytics’ Dynamic Account Modeling™ technology, FraudMAP Access continually monitors the following parameters:

  1. Location from which the account is being accessed
  2. The device being used to access the account
  3. IP address
  4. Day of week and time of day
  5. Frequency patterns

From a regulatory standpoint, FraudMAP Access helps credit unions and banks conform to FFIEC guidance by meeting minimum expectation for anomaly detection at login (for banks and credit unions).

We are interested in the Login, Logout and DeviceRegistered events. The Login event can be used to signal both login success and failure events. The Login event can also be used to send device signature creating a signal of user behavior that FraudMAP tracks on a per user and per session basis. The DeviceRegistered event is used to register a new device, using the uuid and signature created by OpenAM’s DevicePrint module.

Event Data

OpenAM is required to send the following bits of information to the FraudMAP SOAP endpoint:

BrowserPlugins Cookie CookiesEnabled DeviceID FontList HTTPAccept HTTPAcceptCharsets HTTPAcceptEncoding HTTPAcceptLanguage HTTPClientIP HTTPCookie HTTPForwarded HTTPForwardedFor HTTPHost HTTPLocation HTTPProxy HTTPReferer HTTPRequestURI HTTPVia HTTPXClusterClientIP HTTPXForwarded HTTPXForwardedFor HTTPXTrusteerRapport ImmutableUserID IPAddress IPv6Address JavaEnabled LanguageBrowser LanguageSystem LanguageUser Latitude Longitude OSPlatform ScreenResolution SessionID SignOnID TimeZoneOffset UserAgentString UserAgentStringDOM UTCTimestamp

The ImmutableUserID is the key in this mapping process, and is defaulted to the SignOnID, which is the username used to login into OpenAM. Due to privacy concerns, the immutable user id or the sign on id are not sent in the clear, but are SHA1 hashed before being included in the SOAP payload.

OpenAM Configuration Overview

External User Repository

Create a new realm in OpenAM, call it “deviceid” for example. Associate a datastore such as an OpenDJ instance. Check the “Load schema when saved” checkbox. This will ensure the device fingerprint schema is added to the data store. We need this schema because the integration relies on the Device Save module.

Device (Id) Match and Save modules

For this integration the Device Id Match and Save modules in OpenAM can be used as-is. No customizations are necessary. Just ensure the OpenAM schema is loaded into the external user repository you configured into the “deviceid” realm.

Post Authentication Plugin

The HttpServletRequest object is passed into the PaP in the case of a login success and login failure. It contains the following sample data:

Header Name: host-> Header Value: http://<openam-server-hostname>:8080
Header Name: content-type-> Header Value: application/x-www-form-urlencoded
Header Name: origin-> Header Value: http://<openam-server-hostname>:8080
Header Name: cookie-> Header Value: JSESSIONID=496706A47350E1294B0B207E1D9A35B3; AMAuthCookie=AQIC5wM2LY4Sfcz8NstUlg1Chv-_gRP2s-Fj2ZHkPQDYTug.*AAJTSQACMDEAAlNLABMxMDY3MTM1NTMyODY1NTQyNjg4*; amlbcookie=01
Header Name: content-length-> Header Value: 979
Header Name: connection-> Header Value: keep-alive
Header Name: accept-> Header Value: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Header Name: user-agent-> Header Value: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14
Header Name: referer-> Header Value:  http://<openam-server-hostname>:8080/openam/UI/Login
Header Name: accept-language-> Header Value: en-us
Header Name: accept-encoding-> Header Value: gzip, deflate

The user-agent string could be used to detect the type of device used to login.

The value of IDToken0 is also passed into the post authentication module in a Map variable in the case of a login success and failure. A sample value would be:

{"screenWidth":1440,"screenHeight":900,"screenColourDepth":24,"timezone":420,"installedPlugins":"CitrixOnlineWebDeploymentPlugin.plugin;WebEx64.plugin;Default Browser.plugin;Flash Player.plugin;googletalkbrowserplugin.plugin;JavaAppletPlugin.plugin;o1dbrowserplugin.plugin;QuickTime Plugin.plugin;SharePointBrowserPlugin.plugin;;","installedFonts":"cursive;monospace;serif;sans-serif;fantasy;Arial;Arial Black;Arial Narrow;Arial Rounded MT Bold;Bookman Old Style;Century;Century Gothic;Comic Sans MS;Courier;Courier New;Georgia;Impact;Lucida Console;Monotype Corsiva;Papyrus;Tahoma;Times;Times New Roman;Trebuchet MS;Verdana;"}

The timezone offset is the offset in minutes with sign reversed. We simply massage this value in the post authentication module, reverse the sign to get an offset in hours.

In summary, we are able to send most of the information FraudMAP requires using the HttpServletRequest object and the IDToken0 value.

onLoginSuccess()

In the case of a successful login, we read the HttpServletRequest object, and use a JSON parser to parse the IDToken0 value to extract device signature.

onLoginFailure()

The logic here is very similar to onLoginSuccess() with one difference. OpenAM does not send the accountState usually, however, the AMLoginContext class in OpenAM-Core can be customized to include the accountState- active, inactive or locked out- in the Map variable passed into this method. This is not necessary to achieve a successful integration but I decided to do it to take advantage of the “LockedOut” and “UserAccessRestricted” events that FraudMAP accepts among the reasons for login failure.

onLogout()

We reused the logic from onLoginSuccess() to read the HttpServletRequest object but also checked if the logout was user initiated or was the result of a timeout. FraudMAP cares about the difference and it helps to build a more accurate model of user behavior.

Performance Note

OpenAM synchronously calls the PaP and therefore it is paramount we keep delays in creating and sending events to FraudMAP to a minimum. I created a new PostAuthHandler thread to create and fire the event inside each of the login, logout and login failed methods in the PaP. The PostAuthHandler creates the SOAP message and uses org.apache.commons.httpclient.HTTPClient to post the message to FraudMAP’s endpoint.

OpenAM Configuration

Create a new realm

Log into the console as “amadmin”. On the dashboard under the “Access Control” tab

  • Click on the “New..” button
  • Specify the Name as “deviceid”
  • Click OK

Configure the DataStore

  • Click on the deviceid realm, and then click on the “DataStore” tab
  • Delete the existing datastore, and click “New..”
  • Enter the name “DJ” and check the radio button for “OpenDJ”, hit Next
  • Setup the directory configuration details for your OpenDJ
  • Make sure to check “Load schema when saved” check box
  • Click on Save

Create and Configure the Module Instances and Authentication Chain

  • Click on the Authentication tab (OpenAM 12), or the Menu Item (OpenAM 13)
  • Click on “Module Instances”, and click “New” (OpenAM 12), or “Add Module” (OpenAM 13)
  • Create the match and save modules by selecting Device Id (Match) once and Device Id (Save) next

Module instances

  • Click on the match module instance and select the client-side and server-side scripts:

match

  • Specify “hotp” as the Name and select “HOTP” as type, Click OK
  • Click on the “hotp” module instance to edit its properties

hotp

  • Enter a valid gmail account in “Mail Server Authentication Username”
  • Enter a valid “Mail Server Authentication Password”, confirm it
  • Enter a valid “Email From Address”
  • Leave everything else as-is, and click “Save”
  • Chain the HOTP and Device module instances together as shown

Screen Shot 2016-02-02 at 10.03.56 AM

Note that configuring the “match” module instance in Sufficient mode ensures that if an existing device fingerprint were found on the user profile, HOTP will not be triggered since an acceptable device fingerprint was previously registered by the user.
Configure a new Post Authentication Class

  • Click on the Authentication tab
  • Click on “All Core Settings…”, and scroll down to “Post Authentication Processing”
  • Scroll down to “Authentication Post Processing Classes”
  • Add the full name of your PaP class, including the package prefix
  • Click on “Save” and click on “Back to Authentication”
  • Click on “Save” and click on “Back to Access Control”

Ensure users are loaded from DataStore

  • Click on the “deviceid” realm
  • Click on “Subjects”
  • You should see a list of users in your directory

Change test user’s phone number and email

  • Click on the test user, say user.1
  • Edit the phone number to your phone number
  • Edit the email address to your email address
  • This will ensure the SMS sent by the HOTP module arrives at your phone

 

Testing

Login to the realm

  • Browse to the url https://<openam-server.domain>/openam/XUI/#login/&realm=deviceid
  • Enter username and password, and login
  • You should see the following page, click on “Request OTP Code”

hotp1

  • You will receive an SMS on your phone, enter it here and click “Submit OTP Code”

Confirm profile save

  • The Device Save module will ask you to confirm to add the device profile to list of trusted devices

register

  • Select “Yes” and click on “Log In”

Login to view your profile

At this point you will be taken to your user profile page, where you can manage all previously registered devices.

dashboard

Under the hood

Device Registered

In this case, I logged in from a linux virtual machine.

<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><addEvent xmlns="http://com.ga.collector.service/xsd"><requireRiskscore>false</requireRiskscore><serviceId>210057</serviceId><platformId>13</platformId><channel>OLBRetail</channel><payLoad><![CDATA[<?xml version="1.0" encoding="UTF-8"?><GAE:GAEvent xmlns:GAE="http://www.guardiananalytics.com/APIEvents" xmlns:GAET="http://www.guardiananalytics.com/APIEventTypes" xmlns:GAT="http://www.guardiananalytics.com/APIDataTypes"><GAE:DeviceRegistered><GAT:Common><GAT:SchemaVersion>2.00</GAT:SchemaVersion><GAT:TenantID>210057</GAT:TenantID><GAT:Channel>OLBRetail</GAT:Channel><GAT:ProviderEventName>DeviceRegistered</GAT:ProviderEventName></GAT:Common><GAT:RetailSession><GAT:ImmutableUserID>8FC62C1442CC32DAA50D5302E5C997080FB9D747</GAT:ImmutableUserID><GAT:SignOnID>8FC62C1442CC32DAA50D5302E5C997080FB9D747</GAT:SignOnID><GAT:UTCTimestamp>1399562334911</GAT:UTCTimestamp><GAT:IPAddress>127.0.0.1</GAT:IPAddress><GAT:UserAgentString>Mozilla/5.0 (X11; Linux i686; rv:17.0) Gecko/20131029 Firefox/17.0</GAT:UserAgentString><GAT:BrowserHeader><GAT:HTTPAcceptLanguage>en-US,en;q=0.5</GAT:HTTPAcceptLanguage><GAT:HTTPAcceptEncoding>gzip, deflate</GAT:HTTPAcceptEncoding><GAT:HTTPReferer>http://<openam-server.domain>:8080/openam/UI/Login</GAT:HTTPReferer><GAT:HTTPAccept>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</GAT:HTTPAccept></GAT:BrowserHeader></GAT:RetailSession><GAET:DeviceID>790498b4-0f32-4311-960a-629c70ab4424</GAET:DeviceID><GAET:DeviceType>computer</GAET:DeviceType></GAE:DeviceRegistered></GAE:GAEvent>]]></payLoad><key>8d9d0e4c11a19df474c24da34bc6d3c9fd2368ee</key></addEvent></env:Body></env:Envelope>

User Login

I logged in from a mac using a different test user which is the reason the hash of ImmutableUserID is different from the previous example.

LoginStatus: Successful

<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><addEvent xmlns="http://com.ga.collector.service/xsd"><requireRiskscore>false</requireRiskscore><serviceId>210057</serviceId><platformId>13</platformId><channel>OLBRetail</channel><payLoad><![CDATA[<?xml version="1.0" encoding="UTF-8"?><GAE:GAEvent xmlns:GAE="http://www.guardiananalytics.com/APIEvents" xmlns:GAET="http://www.guardiananalytics.com/APIEventTypes" xmlns:GAT="http://www.guardiananalytics.com/APIDataTypes"><GAE:Login><GAT:Common><GAT:SchemaVersion>2.00</GAT:SchemaVersion><GAT:TenantID>xxxxxx</GAT:TenantID><GAT:Channel>OLBRetail</GAT:Channel><GAT:ProviderEventName>Login Attempt</GAT:ProviderEventName></GAT:Common><GAT:RetailSession><GAT:ImmutableUserID>B093FEED33DB091084355C1A464290EE6339A109</GAT:ImmutableUserID><GAT:SignOnID>B093FEED33DB091084355C1A464290EE6339A109</GAT:SignOnID><GAT:UTCTimestamp>1399392974892</GAT:UTCTimestamp><GAT:IPAddress>x.y.z.w</GAT:IPAddress><GAT:UserAgentString>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14</GAT:UserAgentString><GAT:BrowserHeader><GAT:HTTPAcceptLanguage>en-us</GAT:HTTPAcceptLanguage><GAT:HTTPAcceptEncoding>gzip, deflate</GAT:HTTPAcceptEncoding><GAT:HTTPReferer>http://<openam-server.domain>:8080/openam/UI/Login</GAT:HTTPReferer><GAT:HTTPAccept>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</GAT:HTTPAccept></GAT:BrowserHeader><GAT:DeviceAttribute><GAT:FontList>cursive| monospace| serif| sans-serif| fantasy| Arial| Arial Black| Arial Narrow| Arial Rounded MT Bold| Bookman Old Style| Century| Century Gothic| Comic Sans MS| Courier| Courier New| Georgia| Impact| Lucida Console| Monotype Corsiva| Papyrus| Tahoma| Times| Times New Roman| Trebuchet MS| Verdana| </GAT:FontList><GAT:BrowserPlugins>CitrixOnlineWebDeploymentPlugin.plugin| WebEx64.plugin| Default Browser.plugin| Flash Player.plugin| googletalkbrowserplugin.plugin| JavaAppletPlugin.plugin| o1dbrowserplugin.plugin| QuickTime Plugin.plugin| SharePointBrowserPlugin.plugin </GAT:BrowserPlugins><GAT:TimeZoneOffset>-7</GAT:TimeZoneOffset><GAT:ScreenResolution>24|900|1440</GAT:ScreenResolution></GAT:DeviceAttribute></GAT:RetailSession><GAET:LoginStatus>Successful</GAET:LoginStatus></GAE:Login></GAE:GAEvent>]]></payLoad><key>65d67a6d0e87d771d5b843f148d9812d2ec95e10</key></addEvent></env:Body></env:Envelope>

LoginStatus: LockedOut

<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Body><addEvent xmlns="http://com.ga.collector.service/xsd"><requireRiskscore>false</requireRiskscore><serviceId>210057</serviceId><platformId>13</platformId><channel>OLBRetail</channel><payLoad><![CDATA[<?xml version="1.0" encoding="UTF-8"?><GAE:GAEvent xmlns:GAE="http://www.guardiananalytics.com/APIEvents" xmlns:GAET="http://www.guardiananalytics.com/APIEventTypes" xmlns:GAT="http://www.guardiananalytics.com/APIDataTypes"><GAE:Login><GAT:Common><GAT:SchemaVersion>2.00</GAT:SchemaVersion><GAT:TenantID>xxxxxx</GAT:TenantID><GAT:Channel>OLBRetail</GAT:Channel><GAT:ProviderEventName>Login Attempt</GAT:ProviderEventName></GAT:Common><GAT:RetailSession><GAT:ImmutableUserID>B093FEED33DB091084355C1A464290EE6339A109</GAT:ImmutableUserID><GAT:SignOnID>B093FEED33DB091084355C1A464290EE6339A109</GAT:SignOnID><GAT:UTCTimestamp>1399392974892</GAT:UTCTimestamp><GAT:IPAddress>x.y.z.w</GAT:IPAddress><GAT:UserAgentString>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14</GAT:UserAgentString><GAT:BrowserHeader><GAT:HTTPAcceptLanguage>en-us</GAT:HTTPAcceptLanguage><GAT:HTTPAcceptEncoding>gzip, deflate</GAT:HTTPAcceptEncoding><GAT:HTTPReferer>http://<openam-server.domain>:8080/openam/UI/Login</GAT:HTTPReferer><GAT:HTTPAccept>text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</GAT:HTTPAccept></GAT:BrowserHeader><GAT:DeviceAttribute><GAT:FontList>cursive| monospace| serif| sans-serif| fantasy| Arial| Arial Black| Arial Narrow| Arial Rounded MT Bold| Bookman Old Style| Century| Century Gothic| Comic Sans MS| Courier| Courier New| Georgia| Impact| Lucida Console| Monotype Corsiva| Papyrus| Tahoma| Times| Times New Roman| Trebuchet MS| Verdana| </GAT:FontList><GAT:BrowserPlugins>CitrixOnlineWebDeploymentPlugin.plugin| WebEx64.plugin| Default Browser.plugin| Flash Player.plugin| googletalkbrowserplugin.plugin| JavaAppletPlugin.plugin| o1dbrowserplugin.plugin| QuickTime Plugin.plugin| SharePointBrowserPlugin.plugin </GAT:BrowserPlugins><GAT:TimeZoneOffset>-7</GAT:TimeZoneOffset><GAT:ScreenResolution>24|900|1440</GAT:ScreenResolution></GAT:DeviceAttribute></GAT:RetailSession><GAET:LoginStatus>LockedOut</GAET:LoginStatus></GAE:Login></GAE:GAEvent>]]></payLoad><key>65d67a6d0e87d771d5b843f148d9812d2ec95e10</key></addEvent></env:Body></env:Envelope>
Note that this article was first published in the OpenAM Wiki Confluence site for OpenAM 11: OpenAM and Guardian Analytics using Device module  The technical content has been adapted for OpenAM 13. Please let us know if we can improve it in anyway.

Integration with PaloAlto Networks Panorama

Introduction

Palo Alto Networks virtualized firewalls, called the VM-Series support the exact same next-generation firewall and advanced threat prevention features available in their physical form factor appliances, allowing customers to safely enable applications flowing into, and across their private, public and hybrid cloud computing environments. Automation features such as VM monitoring, dynamic address groups and a REST-based API allow developers and administrators to proactively monitor VM changes dynamically feeding that context into security policies, thereby eliminating the policy lag that may occur when the Virtual Machines change.

Consider the following use case:

A customer of Palo Alto Networks has firewalls protecting an insurance & claims Portal. The customer seeks an identity & access management platform with following key capabilities:
a) Onboard millions of existing users from existing internet-facing Directory Server
b) Provide a self registration capability for new customers with a new policy (individual or via employer)
c) Be able to detect portal sessions, and selectively enable enterprise applications in the Portal for customers, affiliates and partners alike.

The ForgeRock powered Palo Alto Networks solution provides all these key capabilities.

Users login to the Portal, protected by OpenAM distributed User Interface living in the DMZ. Upon successful authentication, OpenAM punches application-specific ports in the Palo Alto Networks firewall(s) on behalf of the user via the Palo Alto Networks User-ID API. This powerful real-time action instantly enables user access to Portal iFrames, AJAX widgets (etc) to make inbound API calls to retrieve live policy, insurance or claims content. When the user logs out of Portal, OpenAM instantly closes the application-specific ports via the Palo Alto Networks User-ID API. This real-time action instantly disables access to the specific applications for the user.

This page describes a simpler use case, wherein REST calls are used to log into OpenAM directly, triggering User-Id API calls in the backend to open and subsequently close application ports in the virtualized firewalls managed by Panorama.

 

Technical Overview

All software used in this demo is on evaluation virtual appliances from Palo Alto Networks.

Download, install and configure Panorama 6 to connect to two 5.0.6 firewalls and two 6.0.0 firewalls. For this demo we shall only be using the 6.0.0 firewall.

Note that Panorama has to have the highest version always. The managed firewalls can be the same version as Panorama or older.

Finally, Panorama 6 needs to be run on a 64 bit ESXi host.

Generate an API key that needs to be sent with every REST call using the endpoint: http(s)://hostname/api/?type=keygen&user=username&password=password 

Note that the API returns separate keys each time a keygen query is run. All of the returned keys are valid.

When installations and configurations are done, you should see the virtualized firewalls in a connected state from the Panorama interface:

Write a post authentication plugin (PaP) in OpenAM that uses the Palo Alto Networks REST-based User-ID API to open up an application port in Panorama-managed firewalls.

The PaP creates a user-id mapping file under /tmp, such as the following:

<?xml version="1.0" encoding="UxTF-8"?>
<uid-message>
<payload><login>
<entry blocksize="2" endport="8081" ip="10.0.61.20" name="demo" startport="8080"/></login>
</payload>
<type>update</type>
<version>1.0</version>
</uid-message>

The PaP uploads this XML file to the endpoint: http://hostname/api/?type=user-id&action=set&key=api-key&target=firewall-serial-number

The endpoint is the Panorama listener that dispatches the incoming User-ID API “set” request to the target firewall specified in the target parameter.

Demo

Here is the step by step flow:

Login to OpenAM as demo via curl:

The Post Authentication Plugin creates the API payload and upload it to the Panorama endpoint specifying the target managed firewall.

The User-ID API “punches” an access-grant into the virtualized firewall as shown here. This access-grant happens to never expire in our demo, however, it could be time bounded.

The user logs out via CURL as shown here:

The request is sent to the same target:

The user access, previously granted is now unblocked as shown here.

That sums up this simple demo.

 

This article was first published on the OpenAM Wiki Confluence site: OpenaM and PaloAlto Networks

Google+ Social Login Risk Profiling using ZeroFOX

Introduction

ZeroFOX Enterprise evaluates and records the risk associated with social media users and organizations. This evaluation is conducted through the ZeroFOX Enterprise security analysis engine which analyzes the full social graph for a targeted user to include their associated people, organizations and interactions.

The ZeroFOX Social Risk Score API allows OpenAM to query the ZeroFOX Enterprise Platform RESTful API for risk attributes associated with a given social media asset- social media user or organization. If ZF does not have recent ZeroFOX data on the requested asset, it is immediately submitted for analysis and can be queried again at a later time.

For purposes of this demo with Google Plus, I created a custom OpenAM 13 build that enables chaining the Scripted Authentication Module to the OAuth module. The custom build also enables passing an Authorization header into the httpClient POST API in the server-side script. On every login attempt from a Social Login platform, the Scripted Authentication Module invokes the ZF api with an Authorization header to assess the risk associated with the login.

The following risk attributes can be flagged on a social account and each one of these can be detected from within the Scripted Authentication Module in OpenAM via the ZeroFOX Social Login Risk Score API.

Configuration

From Common Tasks, under the “Configure Social Authentication” menu, select and configure ‘Configure Google Authentication’.

Create a Scripted Authentication Module instance in OpenAM. Add code in the server side script to invoke the ZF API:

httpClient.post("https://api.zerofox.com/1.0/sra/", "{"network":"google+", "user_id":"+userId +"}", {cookies:[], headers:[{"field": "Content-type","value":"application/json"},{"field": "Authorization","value": "forgerock:*******"}]});

Chain the Scripted Authentication Module instance to the GoogleSocialAuthentication instance created in the previous step:

In Google Plus, open a test account and post a phishing link. At this point you should kick off the scan by invoking the ZF API from Postman or using curl. If you do not do it now, the scan is started when you attempt to login into OpenAM using this malicious account, except of course, the Social Login Score is not ready just yet and authentication passes.

Demo

From the OpenAM login page, click on the Google Plus icon to login:

Login as the malicious user and you should immediately see an Authentication denied error. The Scripted Authentication Module checks for high threat indicators and denies login if one or more are found.

Using Postman, invoking the ZF Social Login Score API confirms that phishing links were found on the account and threat level is too high to allow login into OpenAM.

{
  • "phishing": "2015-04-24 17:13:24 UTC",
  • "drugs_and_alcohol": "2015-04-24 17:09:24 UTC",
  • "malware": "2015-04-24 17:13:24 UTC"
}

Impersonation Authentication module for OpenAM

Introduction

Support for impersonation is useful in the enterprise use cases where designated administrators are required to act on behalf of a user in certain scenarios. By impersonating another user an administrator, if authorized to do so, gains access to a restricted view of the user’s profile in the system. This is helpful in situations involving password reset, request-based access and profile updates. However, the design of such a system must call for controls that actively restrict access to the user’s entitlements at the outset. This can be achieved using step-up authentication for gaining access to private user data, and also by using the OpenAM policy engine for performing advanced resource-based decisioning.

Configuration

An OpenAM custom authentication module was written to enable impersonation support. The module requires input of the username of the end-user being impersonated and the administrator credentials. After submitting the username and password, the admin account is authenticated first and then it is also authorized to complete the impersonation request using REST calls to a specified OpenAM Policy endpoint. This policy can be either local or external as we shall examine further. The impersonated user is also validated for being in active status in the system. If all is okay, the administrator is permitted to impersonate and OpenAM creates a session for the impersonated user. The module can be configured using the following gauges to complete the described functions correctly:

  1. Setup the resource-set you want to check policy for. This resource set its nothing but a special URL that invokes policy evaluation for impersonation
  2. The authentication realm you want the administrator to authenticate in. The authentication module allows for realm-specific authentication
  3. The OpenAM server where the policy resides, the realm where the policy resides, and the policy-set name. The policy does not need to be local and can be on a remote policy host
  4. Check whether you want the administrator to be a member of a local group as well, in addition to the external policy authorization.
A step by step account of the workings of the module follows.

Development

Configuration read from Module Instance

options -> {iplanet-am-auth-check-group-membership=[True], iplanet-am-auth-impersonation-hash-enabled=[true], iplanet-am-auth-authentication-realm=[authn], iplanet-am-auth-impersonation-auth-level=[1], iplanet-am-auth-resource-set=[http://openam:8080/openam/index.html], moduleInstanceName=impersonate, iplanet-am-auth-impersonation-id=[Enter the user id to impersonate?], iplanet-am-auth-impersonation-group-name=[impersonation], iplanet-am-auth-openam-server=[http://openam:8080/openam], iplanet-am-auth-policy-realm=[impersonation], iplanet-am-auth-policy-set-name=[impersonation]}

Authorize the administrator locally

In our test scenario, the ‘user.0’ is really an administrative user that has been granted membership to the group named ‘impersonation’, as configured in the module (see above).

We build an AMIdentity object for the group and validate membership.

[AMIdentity object: id=impersonation,ou=group,o=impersonation,ou=services,dc=openam,dc=forgerock,dc=org]
value of attribute: uid=user.0,ou=People,dc=forgerock,dc=com
userName to check: user.0
match found! admin: user.0 allowed to impersonate user: user.1

Authorize the Administrator

Get the ssotoken for the admin who is trying to impersonate via a policy call, and authenticate the user to the realm specified in the config

json/authn/authenticate response-> {"tokenId":"AQIC5wM2LY4Sfcxokjvdayf3ig0oDuQITXRTWT9B_3hq72A.*AAJTSQACMDEAAlNLABI1ODk0Nzg1NTEyNDUzNzcxNDI.*","successUrl":"/openam/console"}
tokenId-> AQIC5wM2LY4Sfcxokjvdayf3ig0oDuQITXRTWT9B_3hq72A.*AAJTSQACMDEAAlNLABI1ODk0Nzg1NTEyNDUzNzcxNDI.*

 

Build the 2nd policy rest call, and use the resource set, openam server, policy set and policy container from the configuration passed to the module.

stringentity-> {"resources": ["http://openam:8080/openam/index.html"],"application":"impersonation", "subject": {"ssoToken":"AQIC5wM2LY4Sfcxokjvdayf3ig0oDuQITXRTWT9B_3hq72A.*AAJTSQACMDEAAlNLABI1ODk0Nzg1NTEyNDUzNzcxNDI.*"}}
json/impersonation/policies?_action=evaluate response-> [{"advices":{},"actions":{"POST":true,"PATCH":true,"GET":true,"DELETE":true,"OPTIONS":true,"PUT":true,"HEAD":true},"resource":"http://openam:8080/openam/index.html","attributes":{"uid":["user.0"],"cn":["Javed Shah"],"roleName":["timeBoundAdmin"]}}]

Custom response attributes can be passed back to the module for further evaluation if needed. For example, a statically defined roleName=timeBoundAdmin could be used to further restrict this impersonation request within the time window specified in the ‘timeBoundAdmin’ control. This example is only given to seed the imagination, the module currently does not restrict the impersonation session using a time window, but this is possible to do.

Parse the JSON response from Policy Evaluation

jsonarray-> {"resource":"http://openam:8080/openam/index.html","attributes":{"uid":["user.0"],"cn":["Javed Shah"],"roleName":["timeBoundAdmin"]},"advices":{},"actions":{"POST":true,"PATCH":true,"GET":true,"DELETE":true,"OPTIONS":true,"HEAD":true,"PUT":true}}
If the ACTION set returned for GET/POST is TRUE, the admin is permitted to impersonate. This could be extended to include other actions as necessary. Finally, destroy the admin session, now that it is not needed anymore and return the impersonated user as the Principal for constructing an OpenAM session.

Demo

Our short demo begins with the administrator being asked for the username of the user they want to impersonate.
Next, the module asks for the admin credentials.
If the administrator is unable to authenticate, or does not belong to the local group, or fails external policy evaluation, the following error screen is shown.
If all checks pass, the adminsitrator is granted the user’s session and logs into OpenAM.

Source

This article was first published on the OpenAM Wiki Confluence site: Impersonation in OpenAM