Ping Federate 7.x with Amazon Web Services (AWS)

Recently I was integrating Amazon Web Services with Ping Federate 7.3 and would like to share the steps I took to make the integration work.

The scenario:

  1. 3 distinct AWS accounts
  2. 1 Active Directory
  3. 1 Ping Federate 7.3 cluster

The goal: have each of the 3 AWS accounts controlled by security groups within Active Directory and facilitated through Ping Federate via SAML assertions.

Step 0: If your Ping Federate isn’t already configured to enable OGNL expressions, enable that [1].

Step 1: Configure an AWS SP Connection in Ping Fed.

You can get the Metadata here: [2]

If memory serves, I ended up trimming down the attribute contract and it looks as follows in my configuration.

SAML Attribute Contract

[NB: I am skipping some configuration stuff here as it should be well represented in the metadata, but would be happy to comment if anyone has questions or points of clarification]

And of course, you will need to export the metadata from Ping and upload it to AWS to complete the SSO configuration.

Step 2: Create IAM Roles that reflect what kind of access you may need in each AWS environment.

1a: In AWS, under the IAM section, create some SSO roles:


AWS Role Trust

Note in my case (screenshot below) I am creating the ‘gcs-aws-admin’ role and so I’d select the “AdministratorAccess” predefined role as show below:

AWS attach policy to role
Finally, review and repeat these steps for each role that you want represented and available for SSO. In my case, I wanted Read-Only, PowerUsers, and Admin roles (all pre-defined).

AWS IAM roles

In this case, I have three roles which I created (note: if you’re following along, these groups are all lower case unless you want a code change in a later section).

These steps will need to be repeated in each Amazon environment.

Step 3: Configure Active Directory groups

To complete this step, you simply need to create Active Directory security groups that match the names created in the IAM role section (for each AWS environment – I only am representing one in the screenshot below).

AD Groups

Step 4: Allowing for Ping to dynamically send group membership to AWS. [Note, when Amazon receives multiple roles, even across multiple subscriptions, it will display them all on a form and you will be asked to select which role to use for login – next screenshot.]


My partially obfuscated ‘attribute contract fulfillment’ section in Ping looks like this (which I will explain momentarily):


The actual code looks like this:

#groupCnOnly = new java.util.ArrayList(),
#groups = #this.get("ds.AD.memberOf") != null ? #this.get("ds.AD.memberOf").getValues() : {},
 #group = new javax.naming.ldap.LdapName(#groups[#i]),
 #cn = #group.getRdn(#group.size() - 1).getValue().toString().toLowerCase(),
 #cn != null && #cn.startsWith("AAA-aws-") ? #groupCnOnly.add("arn:aws:iam::XXXXXX:role/" + #cn + ",arn:aws:iam::XXXXXX:saml-provider/CCC") : null,
 #cn != null && #cn.startsWith("BBB-aws") ? #groupCnOnly.add("arn:aws:iam::YYYYYY:role/" + #cn + ",arn:aws:iam::YYYYYY:saml-provider/CCC") : null,
 #cn != null && #cn.startsWith("gcs-aws") ? #groupCnOnly.add("arn:aws:iam::ZZZZZZ:role/" + #cn + ",arn:aws:iam::ZZZZZZ:saml-provider/GCS") : null,
 #i = #i + 1
#this.get("ds.AD.memberOf") != null ? new org.sourceid.saml20.adapter.attribute.AttributeValue(#groupCnOnly) : null

(Note: In the code above, ‘AAA’, ‘BBB’ = partial obfuscation of role names for other AWS instances.
‘CCC’ is the SAML Provider defined in amazon (screenshot below)
‘XXX’,’YYY’,’ZZZ’ = account numbers).


What does this code do?
This code does the following

  1. create an Array named groupCnOnly
  2. create a variable named ‘groups’ and populate it with the ad ‘memberOf’ attirbute (an empty array if memberOf is empty)
  3. create a variable named ‘i’ as a counter
  4. set-up a loop through the ‘groups’ variable – for each entry:
  5. create a variable called ‘group’ and get LDAP name of the group at index i
  6. create a variable called ‘cn’ and assign it the relative distinguished name (after having converted to string, and setting it to lower case)
  7. if cn isn’t null and if it beings with “environment-aws-“, then add the naming convention defined by amazon
  8. same as 7
  9. same as 7
  10. increment counter variable ‘i’
  11. close loop
  12. if memberOf is not null, then return a new org.sourceid.saml20.adapter.attribute.AttributeValue object (which is passed the newly populated groupCnOnly variable as a parameter)

Lastly – after building that expression in Ping, you cannot really test it because the ad object is references is not going to be available.

Hope that helps!



[1] Enable OGNL Expressions:

[2] Enable SAML2


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s