how the university of arizona addressed sso for office 365 · how the university of arizona...
TRANSCRIPT
How The University of Arizona Addressed SSO for Office 365
Gary Windham
Senior Enterprise Systems Architect The University of Arizona - UITS
[ 2 ]
CONTENTS
How The University of Arizona Addressed SSO for Office 365
bull All Aboard Office 365 ndash Mind the Gap
bull Shibboleth ndash the Sugrureg of SSO
bull Staying Agile ndash Containerization and Cloud Deployment
bull Demo
[ 3 ]
By WillMcC - Own work CC BY-SA 30 httpscommonswikimediaorgwindexphpcurid=4379199
[ 4 ]
Wersquore moving all staff and faculty to Office 365
bull project kickoff was in October 2016
bull motivations
ndash part of larger strategy to migrate the bulk of central IT services to the cloud
ndash avoid having to make further capital expenditures to accommodate growth
bull migrating from on-prem Exchange 2013
ndash ~ 33K mailboxes
ndash ~ 60TB storage
[ 5 ]
Federated SSO with AD will solve all our problems
[ 6 ]
Assumptions and realizations
bull initial assumption was that we would use ADFS with our on-prem Active
Directory for federated SSO
bull as requirements were fleshed-out we realized we had needs not easily
addressed by federated SSO with ADhellip
bull needed to authenticate different types of accounts residing in disjoint OUs
ndash normal user accounts (UA NetIDs)
ndash service accounts
ndash domain admin accounts
[ 7 ]
Assumptions and realizations (cont)
bull MFA authentication with w Duo Security + varying behavior depending on account type
ndash NetIDs use custom-built 2FA registration portal (NetID+)
ndash service accounts and domain admin accounts arent NetIDs
bull required separate Duo application integrations to handle enrollment via the Duo Web SDK
bull app passwords
ndash we have a significant number of legacy clients
bull cant use Microsofts modern authentication (ADAL)
bull can only use ECP for federated authentication ndash ECP endpoint not supported by AD
ndash we didnt want to completely sacrifice MFA for these clients
ndash plan provide application-specific password functionality
ndash couldnrsquot use Azure app passwords unless we also adopted Azure MFA
bull campus already has significant investment in Duo
[ 8 ]
The long tail of email clients
bull Office365 supports Modern Authentication
ndash ADAL (Azure AD Authentication Libraries)
ndash Facilitates web SSO authentication in native applications
ndash Makes MFA feasible with native email clients
bull recent Outlook clients support Modern Authentication
ndash enabled by default in Office 2016
ndash available but not enabled by default in Office 2013
bull very heterogeneous email client landscape
ndash older versions of Outlook
ndash Apple Mail
ndash Thunderbird
ndash various 3rd-party mobile POPIMAP clients PINE mutt any conceivable thing faculty might install
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 2 ]
CONTENTS
How The University of Arizona Addressed SSO for Office 365
bull All Aboard Office 365 ndash Mind the Gap
bull Shibboleth ndash the Sugrureg of SSO
bull Staying Agile ndash Containerization and Cloud Deployment
bull Demo
[ 3 ]
By WillMcC - Own work CC BY-SA 30 httpscommonswikimediaorgwindexphpcurid=4379199
[ 4 ]
Wersquore moving all staff and faculty to Office 365
bull project kickoff was in October 2016
bull motivations
ndash part of larger strategy to migrate the bulk of central IT services to the cloud
ndash avoid having to make further capital expenditures to accommodate growth
bull migrating from on-prem Exchange 2013
ndash ~ 33K mailboxes
ndash ~ 60TB storage
[ 5 ]
Federated SSO with AD will solve all our problems
[ 6 ]
Assumptions and realizations
bull initial assumption was that we would use ADFS with our on-prem Active
Directory for federated SSO
bull as requirements were fleshed-out we realized we had needs not easily
addressed by federated SSO with ADhellip
bull needed to authenticate different types of accounts residing in disjoint OUs
ndash normal user accounts (UA NetIDs)
ndash service accounts
ndash domain admin accounts
[ 7 ]
Assumptions and realizations (cont)
bull MFA authentication with w Duo Security + varying behavior depending on account type
ndash NetIDs use custom-built 2FA registration portal (NetID+)
ndash service accounts and domain admin accounts arent NetIDs
bull required separate Duo application integrations to handle enrollment via the Duo Web SDK
bull app passwords
ndash we have a significant number of legacy clients
bull cant use Microsofts modern authentication (ADAL)
bull can only use ECP for federated authentication ndash ECP endpoint not supported by AD
ndash we didnt want to completely sacrifice MFA for these clients
ndash plan provide application-specific password functionality
ndash couldnrsquot use Azure app passwords unless we also adopted Azure MFA
bull campus already has significant investment in Duo
[ 8 ]
The long tail of email clients
bull Office365 supports Modern Authentication
ndash ADAL (Azure AD Authentication Libraries)
ndash Facilitates web SSO authentication in native applications
ndash Makes MFA feasible with native email clients
bull recent Outlook clients support Modern Authentication
ndash enabled by default in Office 2016
ndash available but not enabled by default in Office 2013
bull very heterogeneous email client landscape
ndash older versions of Outlook
ndash Apple Mail
ndash Thunderbird
ndash various 3rd-party mobile POPIMAP clients PINE mutt any conceivable thing faculty might install
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 3 ]
By WillMcC - Own work CC BY-SA 30 httpscommonswikimediaorgwindexphpcurid=4379199
[ 4 ]
Wersquore moving all staff and faculty to Office 365
bull project kickoff was in October 2016
bull motivations
ndash part of larger strategy to migrate the bulk of central IT services to the cloud
ndash avoid having to make further capital expenditures to accommodate growth
bull migrating from on-prem Exchange 2013
ndash ~ 33K mailboxes
ndash ~ 60TB storage
[ 5 ]
Federated SSO with AD will solve all our problems
[ 6 ]
Assumptions and realizations
bull initial assumption was that we would use ADFS with our on-prem Active
Directory for federated SSO
bull as requirements were fleshed-out we realized we had needs not easily
addressed by federated SSO with ADhellip
bull needed to authenticate different types of accounts residing in disjoint OUs
ndash normal user accounts (UA NetIDs)
ndash service accounts
ndash domain admin accounts
[ 7 ]
Assumptions and realizations (cont)
bull MFA authentication with w Duo Security + varying behavior depending on account type
ndash NetIDs use custom-built 2FA registration portal (NetID+)
ndash service accounts and domain admin accounts arent NetIDs
bull required separate Duo application integrations to handle enrollment via the Duo Web SDK
bull app passwords
ndash we have a significant number of legacy clients
bull cant use Microsofts modern authentication (ADAL)
bull can only use ECP for federated authentication ndash ECP endpoint not supported by AD
ndash we didnt want to completely sacrifice MFA for these clients
ndash plan provide application-specific password functionality
ndash couldnrsquot use Azure app passwords unless we also adopted Azure MFA
bull campus already has significant investment in Duo
[ 8 ]
The long tail of email clients
bull Office365 supports Modern Authentication
ndash ADAL (Azure AD Authentication Libraries)
ndash Facilitates web SSO authentication in native applications
ndash Makes MFA feasible with native email clients
bull recent Outlook clients support Modern Authentication
ndash enabled by default in Office 2016
ndash available but not enabled by default in Office 2013
bull very heterogeneous email client landscape
ndash older versions of Outlook
ndash Apple Mail
ndash Thunderbird
ndash various 3rd-party mobile POPIMAP clients PINE mutt any conceivable thing faculty might install
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 4 ]
Wersquore moving all staff and faculty to Office 365
bull project kickoff was in October 2016
bull motivations
ndash part of larger strategy to migrate the bulk of central IT services to the cloud
ndash avoid having to make further capital expenditures to accommodate growth
bull migrating from on-prem Exchange 2013
ndash ~ 33K mailboxes
ndash ~ 60TB storage
[ 5 ]
Federated SSO with AD will solve all our problems
[ 6 ]
Assumptions and realizations
bull initial assumption was that we would use ADFS with our on-prem Active
Directory for federated SSO
bull as requirements were fleshed-out we realized we had needs not easily
addressed by federated SSO with ADhellip
bull needed to authenticate different types of accounts residing in disjoint OUs
ndash normal user accounts (UA NetIDs)
ndash service accounts
ndash domain admin accounts
[ 7 ]
Assumptions and realizations (cont)
bull MFA authentication with w Duo Security + varying behavior depending on account type
ndash NetIDs use custom-built 2FA registration portal (NetID+)
ndash service accounts and domain admin accounts arent NetIDs
bull required separate Duo application integrations to handle enrollment via the Duo Web SDK
bull app passwords
ndash we have a significant number of legacy clients
bull cant use Microsofts modern authentication (ADAL)
bull can only use ECP for federated authentication ndash ECP endpoint not supported by AD
ndash we didnt want to completely sacrifice MFA for these clients
ndash plan provide application-specific password functionality
ndash couldnrsquot use Azure app passwords unless we also adopted Azure MFA
bull campus already has significant investment in Duo
[ 8 ]
The long tail of email clients
bull Office365 supports Modern Authentication
ndash ADAL (Azure AD Authentication Libraries)
ndash Facilitates web SSO authentication in native applications
ndash Makes MFA feasible with native email clients
bull recent Outlook clients support Modern Authentication
ndash enabled by default in Office 2016
ndash available but not enabled by default in Office 2013
bull very heterogeneous email client landscape
ndash older versions of Outlook
ndash Apple Mail
ndash Thunderbird
ndash various 3rd-party mobile POPIMAP clients PINE mutt any conceivable thing faculty might install
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 5 ]
Federated SSO with AD will solve all our problems
[ 6 ]
Assumptions and realizations
bull initial assumption was that we would use ADFS with our on-prem Active
Directory for federated SSO
bull as requirements were fleshed-out we realized we had needs not easily
addressed by federated SSO with ADhellip
bull needed to authenticate different types of accounts residing in disjoint OUs
ndash normal user accounts (UA NetIDs)
ndash service accounts
ndash domain admin accounts
[ 7 ]
Assumptions and realizations (cont)
bull MFA authentication with w Duo Security + varying behavior depending on account type
ndash NetIDs use custom-built 2FA registration portal (NetID+)
ndash service accounts and domain admin accounts arent NetIDs
bull required separate Duo application integrations to handle enrollment via the Duo Web SDK
bull app passwords
ndash we have a significant number of legacy clients
bull cant use Microsofts modern authentication (ADAL)
bull can only use ECP for federated authentication ndash ECP endpoint not supported by AD
ndash we didnt want to completely sacrifice MFA for these clients
ndash plan provide application-specific password functionality
ndash couldnrsquot use Azure app passwords unless we also adopted Azure MFA
bull campus already has significant investment in Duo
[ 8 ]
The long tail of email clients
bull Office365 supports Modern Authentication
ndash ADAL (Azure AD Authentication Libraries)
ndash Facilitates web SSO authentication in native applications
ndash Makes MFA feasible with native email clients
bull recent Outlook clients support Modern Authentication
ndash enabled by default in Office 2016
ndash available but not enabled by default in Office 2013
bull very heterogeneous email client landscape
ndash older versions of Outlook
ndash Apple Mail
ndash Thunderbird
ndash various 3rd-party mobile POPIMAP clients PINE mutt any conceivable thing faculty might install
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 6 ]
Assumptions and realizations
bull initial assumption was that we would use ADFS with our on-prem Active
Directory for federated SSO
bull as requirements were fleshed-out we realized we had needs not easily
addressed by federated SSO with ADhellip
bull needed to authenticate different types of accounts residing in disjoint OUs
ndash normal user accounts (UA NetIDs)
ndash service accounts
ndash domain admin accounts
[ 7 ]
Assumptions and realizations (cont)
bull MFA authentication with w Duo Security + varying behavior depending on account type
ndash NetIDs use custom-built 2FA registration portal (NetID+)
ndash service accounts and domain admin accounts arent NetIDs
bull required separate Duo application integrations to handle enrollment via the Duo Web SDK
bull app passwords
ndash we have a significant number of legacy clients
bull cant use Microsofts modern authentication (ADAL)
bull can only use ECP for federated authentication ndash ECP endpoint not supported by AD
ndash we didnt want to completely sacrifice MFA for these clients
ndash plan provide application-specific password functionality
ndash couldnrsquot use Azure app passwords unless we also adopted Azure MFA
bull campus already has significant investment in Duo
[ 8 ]
The long tail of email clients
bull Office365 supports Modern Authentication
ndash ADAL (Azure AD Authentication Libraries)
ndash Facilitates web SSO authentication in native applications
ndash Makes MFA feasible with native email clients
bull recent Outlook clients support Modern Authentication
ndash enabled by default in Office 2016
ndash available but not enabled by default in Office 2013
bull very heterogeneous email client landscape
ndash older versions of Outlook
ndash Apple Mail
ndash Thunderbird
ndash various 3rd-party mobile POPIMAP clients PINE mutt any conceivable thing faculty might install
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 7 ]
Assumptions and realizations (cont)
bull MFA authentication with w Duo Security + varying behavior depending on account type
ndash NetIDs use custom-built 2FA registration portal (NetID+)
ndash service accounts and domain admin accounts arent NetIDs
bull required separate Duo application integrations to handle enrollment via the Duo Web SDK
bull app passwords
ndash we have a significant number of legacy clients
bull cant use Microsofts modern authentication (ADAL)
bull can only use ECP for federated authentication ndash ECP endpoint not supported by AD
ndash we didnt want to completely sacrifice MFA for these clients
ndash plan provide application-specific password functionality
ndash couldnrsquot use Azure app passwords unless we also adopted Azure MFA
bull campus already has significant investment in Duo
[ 8 ]
The long tail of email clients
bull Office365 supports Modern Authentication
ndash ADAL (Azure AD Authentication Libraries)
ndash Facilitates web SSO authentication in native applications
ndash Makes MFA feasible with native email clients
bull recent Outlook clients support Modern Authentication
ndash enabled by default in Office 2016
ndash available but not enabled by default in Office 2013
bull very heterogeneous email client landscape
ndash older versions of Outlook
ndash Apple Mail
ndash Thunderbird
ndash various 3rd-party mobile POPIMAP clients PINE mutt any conceivable thing faculty might install
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 8 ]
The long tail of email clients
bull Office365 supports Modern Authentication
ndash ADAL (Azure AD Authentication Libraries)
ndash Facilitates web SSO authentication in native applications
ndash Makes MFA feasible with native email clients
bull recent Outlook clients support Modern Authentication
ndash enabled by default in Office 2016
ndash available but not enabled by default in Office 2013
bull very heterogeneous email client landscape
ndash older versions of Outlook
ndash Apple Mail
ndash Thunderbird
ndash various 3rd-party mobile POPIMAP clients PINE mutt any conceivable thing faculty might install
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 9 ]
Shibboleth mdash The Sugru reg of SSO
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 10 ]
Shibboleth mdash The Sugru reg of SSO
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 11 ]
Shibboleth mdash The Sugru reg of SSO
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 12 ]
Shibboleth mdash The Sugru reg of SSO
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 13 ]
Shibboleth mdash The Sugru reg of SSO
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 14 ]
Shibboleth mdash The Sugru reg of SSO
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 15 ]
Shibboleth IdP Environment
bull Shibboleth IdP v331 running in Docker containers
ndash Centos 7
ndash Oracle JDK 8
ndash Jetty 9
bull Authentication Components
ndash MultiFactorAuthnConfiguration
ndash DuoAuthnConfiguration
ndash JAASAuthnConfiguration
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 16 ]
Challenge 1 ndash Authenticate via LDAP BIND against 3 disjoint AD OUs
bull need to attempt authentications against 3 different OUs in Active Directory
bull OUs house separate user populations
ndash normal users (NetIDs)
ndash service accounts
ndash delegated domain admins
bull need to keep track of which OU user was authenticated against in order to use
different MFA configurations in subsequent step
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 17 ]
JAAS to the rescue
bull JAAS = Java Authentication and Authorization Service
bull (from the Shibboleth Wiki) JAAS is a desktop authentication mechanism in
Java that has been commonly misappropriated as a server-side technology
bull PAM-like can have multiple configurations that are tried in succession until
one succeeds
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 18 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 19 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct base DNs
(could be distinct servers)
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 20 ]
jaasconfigCatnetNetIdAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=NetIDDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-netid-pool
CatnetAdminAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=AdminDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-admin-pool
CatnetSvcAcctAuth orgldaptivejaasLdapLoginModule requiredldapUrl=ldapsactivedirectoryarizonaedu636baseDn=OU=RCUDC=ArizonaDC=edubindDn=CN=__ua-shibb-bindOU=Service AccountsDC=ArizonaDC=edubindCredential=ltpasswordgtuseStartTLS=falsecredentialConfig=trustCertificates=fileoptshibboleth-idpcredentialsad-cert-chainpemuserFilter=(sAMAccountName=user)dnResolver=orgldaptiveauthPooledSearchDnResolverauthenticationHandler=orgldaptiveauthPooledBindAuthenticationHandlerminPoolSize=3maxPoolSize=10validatePeriodically=truevalidator=orgldaptivepoolSearchValidatorpruneStrategy=orgldaptivepoolIdlePruneStrategyprunePeriod=60000idleTime=120000subtreeSearch=truecacheId=catnet-svcacct-pool
Distinct LDAP connection pools
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 21 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 22 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 23 ]
Challenge 2 ndash provide ECP access for legacy clients in secure way
bull need to allow older versions of Outlook POPIMAP clients etc to continue
authenticating against Office 365
bull no simple way for these clients to directly use MFA
bull donrsquot want to expose escape hatch to MFA enforcement
How do we tackle this challenge
Build app password service (agrave la Google or Azure MFA) which stores
application-specific passwords in a separate store and requires same level of
authentication as logging-in to O365
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 24 ]
Configuring ECP in Shibboleth
bull what is ECP
ndash Enhanced Client or Proxy
ndash client that is not a browser
ndash The ECP profile is an adaptation of the SAML profile used for Browser SSO with the
parts that were designed around the limitations of a browser removed
bull configuring ECP for password-based authN is pretty straightforward and is
described on Shibboleth wiki [1]
bull how do we know to access app password store for authentication credentials
when ECP binding is used (will get to this in next challenge)
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 25 ]
App Password Store
bull requirements are simple
ndash user can have unlimited number of app passwords
ndash passwords are stored in hashed format (using PBKDF2)
ndash store createdOn lastUsed and simple text description (eg name of app that will be using password)
bull where to store passwords
ndash Shib IdP will have multiple nodes (for HA) so we need a shared data source
ndash dedicated relational DB seems like overkill
ndash ended up settling on AWS DynamoDB
bull will be running Shib IdP hosts in AWS
bull minimal costmaintenanceeffort
bull not really worried about backing up data (beyond replication for HA purposes)
bull app password management application
ndash serverless NodeJS application also running in AWS (using Lambda and API Gateway)
ndash use Passportjs for SAML authentication against our IdP
ndash use AWS Javascript SDK to interface with DynamoDB
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 26 ]
Interfacing the password store w Shib
bull DynamoDB has a low-level HTTP-based API plus numerous higher-level API
bindings (eg Java Python Javascript etc)
bull since we were already using JAAS we developed a simple JAAS module
based on Jan Oppolzerrsquos jaas-rdbms-hashed [2]
bull not much effort
ndash had to adapt the Utils class (which performs password hashing) to use
PBKDF2WithHmacSHA256 instead of SHA256
ndash created a DynamoDB client factory that uses synchronized HashMap to allow for
multiple JAAS DynamoDB login configs each with their own client connection pool
ndash implement login() method of javaxsecurityauthspiLoginModule to
interface with DynamoDB
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 27 ]
Add new JAAS configuration
bull create a jar for our JAAS module amp drop it in Shib IdP distributionrsquos webappsWEB-INFlib folder
bull add following to confauthnjaasconfig
ECPPasswordAuth eduarizonauitssiajaasdynamodbDynamoDBLogin requiredregion=us-west-2table=o365-app-pwpartitionKey=netidsortKey=hashedPwpwSalt=random stringcacheId=ddb
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 28 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 29 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 30 ]
Challenge 3 ndash Configure separate MFA policies per OU
bull need to use different Duo application integration for principals in each OU
bull regular users (NetIDs) enroll in Duo via custom University-branded portal
bull service accounts and OU admin accounts need to enroll via Duo Web UI
bull bonus challenge provide mechanism to allow administrative bypass of Duo
2FA in special situations
How do we tackle this challenge
Shib allows the use of a Function bean for dynamically returning a set of JAAS
configuration names at runtime along with an optional set of principal types We
use these principal types in the MFA authn flow
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 31 ]
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 32 ]
JAASLoginConfigurationsMapltutilmapgtltentry1gtltentry2gt
hellipltentryngt
JAASLoginConfigurationsltutillistgt
ltbeangtparent=shibbolethPair
ltpropertygtname=first
value=JAASConfigName
ltpropertygtname=second
ref=
ltbeangtclass=javaxsecurityauthSubject
bull constructor-arg1=falsebull constructor-arg2=refbull constructor-arg3=refbull constructor-arg4=ref
CustomPTSetltutilsetgtvalue-type=
javasecurityPrincipalltrefgtltrefgt
hellip
CustomSubjectPubCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
CustomSubjectPrivCredsltutilsetgt (empty)
value-type=javasecurityPrincipal
PasswordProtectedTransportPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTransport
NetIdDuoPTltbeangt
parent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfa
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 33 ]
jaas-authn-configxml additions
lt-- Custom Principal types for JAAS Login Config mapping --gtltbean id=PasswordProtectedTransportPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordProtectedTra
nsportgtltbean id=PasswordPT
parent=shibbolethSAML2AuthnContextClassRefcclassRef=urnoasisnamestcSAML20acclassesPasswordgt
ltbean id=NetIdDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassesnetidmfagt
ltbean id=CatnetDuoPTparent=shibbolethSAML2AuthnContextClassRefcclassRef=httparizonaeduacclassescatnetmfagt
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 34 ]
jaas-authn-configxml additions (cont)
lt-- lists of custom principal types for each login config --gtltutilset id=ECPPasswordAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgt
ltutilsetgtltutilset id=CatnetNetIdAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=NetIdDuoPTgt
ltutilsetgtltutilset id=CatnetAdminAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgtltutilset id=CatnetSvcAcctAuthPTSet value-type=javasecurityPrincipalgt
ltref bean=PasswordProtectedTransportPTgtltref bean=PasswordPTgtltref bean=CatnetDuoPTgt
ltutilsetgt
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 35 ]
jaas-authn-configxml additions (cont)
lt-- empty pub amp private credentials lists for Subjects --gtltutilset id=ECPPasswordAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=ECPPasswordAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetNetIdAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetAdminAuthSubjectPrivCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPubCreds
value-type=javasecurityPrincipalgtltutilset id=CatnetSvcAcctAuthSubjectPrivCreds
value-type=javasecurityPrincipalgt
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 36 ]
jaas-authn-configxml additions (cont)
lt-- javaxsecurityauthSubject beans for each login config --gtltbean id=ECPPasswordAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=ECPPasswordAuthPTSetgtltconstructor-arg ref=ECPPasswordAuthSubjectPubCredsgtltconstructor-arg ref=ECPPasswordAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetNetIdAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetNetIdAuthPTSetgtltconstructor-arg ref=CatnetNetIdAuthSubjectPubCredsgtltconstructor-arg ref=CatnetNetIdAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetAdminAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetAdminAuthPTSetgtltconstructor-arg ref=CatnetAdminAuthSubjectPubCredsgtltconstructor-arg ref=CatnetAdminAuthSubjectPrivCredsgt
ltbeangtltbean id=CatnetSvcAcctAuthSubject class=javaxsecurityauthSubjectgt
ltconstructor-arg value=falsegtltconstructor-arg ref=CatnetSvcAcctAuthPTSetgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPubCredsgtltconstructor-arg ref=CatnetSvcAcctAuthSubjectPrivCredsgt
ltbeangt
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 37 ]
jaas-authn-configxml additions (cont)
lt-- Collections of JAAS login configs to custom principal lists --gtltutillist id=JAASECPLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtECPPasswordAuthltvaluegtltpropertygtltproperty name=second ref=ECPPasswordAuthSubjectgt
ltbeangtltutillistgtltutillist id=JAASDefaultLoginConfigurationsgt
ltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetNetIdAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetNetIdAuthSubjectgtltbeangtltbean parent=shibbolethPairgtltproperty name=firstgtltvaluegtCatnetAdminAuthltvaluegtltpropertygt
ltproperty name=second ref=CatnetAdminAuthSubjectgtltbeangtltbean parent=shibbolethPairgt
ltproperty name=firstgtltvaluegtCatnetSvcAcctAuthltvaluegtltpropertygtltproperty name=second ref=CatnetSvcAcctAuthSubjectgt
ltbeangtltutillistgt
lt-- map of SAML Binding to JAAS login configurations lists --gtltutilmap id=JAASLoginConfigurationsMapgt
ltentry key=ECP value-ref=JAASECPLoginConfigurationsgtltentry key=default value-ref=JAASDefaultLoginConfigurationsgt
ltutilmapgt
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 38 ]
Scripting the JAAS LoginConfigStrategy
bull now that we have our JAASLoginConfigurationsMap we can pass it to the
shibbolethauthnJAASLoginConfigStrategy bean (introduced in Shib
IdP 330)ltbean id=shibbolethauthnJAASLoginConfigStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=JAASLoginConfigurationsMapgt
ltconstructor-arggtltvaluegt
lt[CDATA[ Check if SAML binding is ECP or default (anything else)auditCtx = inputgetSubcontext(netshibbolethidpprofilecontextAuditContext)samlAuditFields = Javatype(netshibbolethidpsamlprofileSAMLAuditFields)bindings = auditCtxgetFieldValues(samlAuditFieldsREQUEST_BINDING)iter = bindingsiterator()isECP = falsewhile (iterhasNext() ampamp isECP)
b = iternext()if (b === urnoasisnamestcSAML20bindingsSOAP)
isECP = true
if (isECP)
loginConfig = customget(ECP) else
loginConfig = customget(default)loginConfig
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 39 ]
MultiFactorAuthnConfiguration
bull The authnMFA login flow is literally the greatest thing since sliced bread
bull allows you to combine multiple login flow via script or code glue to provide highly-
customized composite flows
bull described in-depth on the wiki [3]
bull we define a shibbolethauthnMFATransitionMap that includes 2 steps our initial
password authentication and our (conditional) second-factor authentication (Duo)
ndash password authentication is managed by the authnPassword login flow
bull delegates authentication to JAAS backend
ndash second-factor authentication managed by authnDuo login flow based on conditional output of
inline script
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 40 ]
shibbolethauthnMFATransitionMap (mfa-authn-configxml)
ltutilmap id=shibbolethauthnMFATransitionMapgtlt-- First rule runs the Password login flow --gtltentry key=gt
ltbean parent=shibbolethauthnMFATransitionpnextFlow=authnPasswordgt
ltentrygt
lt--Second rule runs a function if Password succeeds
to determine whether Duo authn is required--gtltentry key=authnPasswordgt
ltbean parent=shibbolethauthnMFATransitionpnextFlowStrategy-ref=checkSecondFactorgt
ltentrygt
lt-- An implicit final rule will return whatever the final flowreturns --gt
ltutilmapgt
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 41 ]
checkSecondFactor inline script (mfa-authn-configxml)lt-- script to see if second factor is required --gtltbean id=checkSecondFactor parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=shibbolethAttributeResolverServicegtltconstructor-arggt
ltvaluegtlt[CDATA[
nextFlow = null
Check if password flow returned mfa supported principal typeauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)principals = passwordAuthResultgetSupportedPrincipals(Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)class)
iter = principalsiterator()while (nextFlow == null ampamp iterhasNext())
pr = iternext()if (prgetName()endsWith(mfa))
nextFlow = authnDuo
if user in bypass group dont pass to Duoif (nextFlow === authnDuo)
resCtx = inputgetSubcontext(netshibbolethidpattributeresolvercontextAttributeResolutionContext true)
Look up the usernameusernameLookupStrategyClass = Javatype(netshibbolethidpsessioncontextnavigateCanonicalUsernameLookupStrategy)usernameLookupStrategy = new usernameLookupStrategyClass()username = usernameLookupStrategyapply(input)resCtxsetPrincipal(username)
resolve the isMemberOf attributeresCtxresolveAttributes(custom)
Check for isMemberOf value that allows bypass of Duoattribute = resCtxgetResolvedIdPAttributes()get(isMemberOf)valueType = Javatype(netshibbolethidpattributeStringAttributeValue)if (attribute = null ampamp attributegetValues()contains(new valueType(arizonaeduservicesenterprisecatnet20shibbolethduo-bypass))) nextFlow = null
nextFlow pass control to second factor or end with the first
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 42 ]
How do we use different Duo configurations for different user types
bull once again Shibboleth has you covered
ndash multiple Integrations
ndash DuoIntegrationStrategy (dynamic determination of strategy at run-time)
ndash integration-specific principal sets (segregate categories of Duo auth based on principal type)
bull again described in detail on the wiki [4]
bull in UArsquos case we configured two netshibbolethidpauthnduoBasicDuoIntegration
beans
ndash each one tied to one of our custom principal types
bull httparizonaeduacclassesnetidmfa
bull httparizonaeduacclassescatnetmfa
ndash recall these principal types are set by the specific JAAS config which successfully authenticates
the user
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 43 ]
Duo multiple integrations and principal types additions (duo-authn-configxml)
lt-- Turn off default behavior in favor of integration-specific principals below --gtltutilconstant id=shibbolethauthnDuoaddDefaultPrincipals static-field=javalangBooleanFALSEgt
ltbeanid=DefaultDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpduoapiHostnonepapplicationKey=idpduoapplicationKeynonepintegrationKey=idpduointegrationKeynonepsecretKey=idpduosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassesnetidmfagt
ltlistgtltpropertygt
ltbeangt
ltbeanid=CatnetDuoclass=netshibbolethidpauthnduoBasicDuoIntegrationpAPIHost=idpcatnetOnlyDuoapiHostnonepapplicationKey=idpcatnetOnlyDuoapplicationKeynonepintegrationKey=idpcatnetOnlyDuointegrationKeynonepsecretKey=idpcatnetOnlyDuosecretKeynonegtltproperty name=supportedPrincipalsgt
ltlistgtltbean parent=shibbolethSAML2AuthnContextClassRef cclassRef=httparizonaeduacclassescatnetmfagt
ltlistgtltpropertygt
ltbeangt
ltutillist id=DuoIntegrationListgtltref bean=CatnetDuogtltref bean=DefaultDuogt
ltutillistgt
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 44 ]
scripted Duo integration strategy (duo-authn-configxml)
ltbean id=shibbolethauthnDuoDuoIntegrationStrategy parent=shibbolethContextFunctionsScripted factory-method=inlineScript pcustomObject-ref=DuoIntegrationListgtltconstructor-arggt
ltvaluegtlt[CDATA[
duo = nullauthCtx = inputgetSubcontext(netshibbolethidpauthncontextAuthenticationContext)mfaCtx = authCtxgetSubcontext(netshibbolethidpauthncontextMultiFactorAuthenticationContext)passwordAuthResult = mfaCtxgetActiveResults()get(authnPassword)var clz = Javatype(netshibbolethidpsamlauthnprincipalAuthnContextClassRefPrincipal)classprincipals = passwordAuthResultgetSupportedPrincipals(clz)
iter = customiterator()
while (duo == null ampamp iterhasNext()) duo = iternext()supportedPrincipals = duogetSupportedPrincipals(clz) check if we got a match based on RequestedPrincipalContext and check current result context if notthisDuo = duoduo = nullif (passwordAuthResult = null)
prIter = principalsiterator()supPrIter = supportedPrincipalsiterator()while (duo == null ampamp prIterhasNext())
pr = prIternext()while (duo == null ampamp supPrIterhasNext())
supPr = supPrIternext()if (prgetName() == supPrgetName())
duo = thisDuo
duo return appropriate Duo config
]]gtltvaluegt
ltconstructor-arggtltbeangt
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 45 ]
Staying Agile ndash Containerization and Cloud Deployment
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 46 ]
Agility Goals
bull want everything (configuration + code) in SCCS
bull avoid having to maintain updates to metadata configuration files etc on the individual IdP backends
bull minimize effort in deploying Shib IdP software updates
bull maximize flexibility in scaling Shib IdP backends
bull perform bluegreen deployments of IdP configurationcode changes
bull minimize managementcosts of support infrastructure needed for Shib IdP ecosystem eg
ndash relational databases
ndash HA middleware
ndash application server for app passwords
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 47 ]
Agility Decision 1 ndash Dockerize Shib IdP
bull in-house experience running Docker Containers
bull makes it easier to maintain deployable IdP along with configurationmetadata
in SCCS
bull luckily we didnrsquot have to re-invent the wheel
ndash Uniconrsquos shibboleth-idp-dockerized IdP base image [5]
ndash created own Dockerfile based on Uniconrsquos base image with a few modifications
bull removed SSL config from Jetty
bull used Oracle JVM instead of OpenJDK [6]
bull removed standard spymemcached jar (needed to use memcached as shared ticket cache) and
replaced with AWS Elasticache-enabled version
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 48 ]
Agility Decision 2 ndash run IdP containers in AWS ECS
bull ECS = EC2 Container Service
ndash Amazon EC2 Container Service (ECS) is a highly scalable high performance
container management service that supports Docker containers and allows you to
easily run applications on a managed cluster of Amazon EC2 instances
bull allows us to schedule number of IdP tasks (containers) based on load
resource utilization etc
bull versioning of tasks allows us to perform bluegreen deployments when
updating Shib IdP configuration or code
bull could be done equally well on top of container orchestration frameworks like
Kubernetes or Mesos
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 49 ]
ECS Cluster
Container Instance 1
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 50 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
Scaling
Policies
invokesfeeds
CloudWatch Metrics CloudWatch Alarms
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 51 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 52 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
CloudWatch Metrics CloudWatch Alarms
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 53 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 54 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 55 ]
ECS Cluster
Service ATask 1
Container Instance 1 Container Instance 2
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
Service ATask 3
Service ATask 4
CloudWatch Metrics CloudWatch Alarms
Service ATask 5
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 56 ]
ECS Cluster
Service ATask 1
Container Instance 1
1) 1 EC2 Container instance 1
Service A task
2) Increased load triggers alarm
which executes application auto-
scaling policy
3) ECS cluster metrics trigger EC2
auto-scaling policy
4) Further application load
increase executes
application auto-scaling
launching additional
service A tasks on new
EC2 container instance
Scaling
Policies
invokesfeeds
Service ATask 2
CloudWatch Metrics CloudWatch Alarms5) As load
decreases auto-
scaling can scale-in
service A tasks and
EC2 container
instances
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 57 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
ECS Cluster
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 58 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
ECS Cluster
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 59 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
ECS Cluster
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 60 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
ECS Cluster
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 61 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
ECS Cluster
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 62 ]
ALB
Task 1 Task 2
Task 1 Task 2
Service A
Service B
Container Instance 1 Container Instance 2
Service A
Task
Definition
version nECR
latest
Service A
Task
Definition
version n+1
1) New task definition version
created
2) Service A task version updated
Task 3 Task 4
3) ECS launches new Service A
tasks and registers them with ALB
4) ALB connection
draining on previous tasks
begins
5) As connections drained
ECS kills old tasks
ECS Cluster
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 63 ]
Agility Decision 3 ndash use AWS ElastiCache for MemcachedStorageService
bull need shared storage mechanism for session storage and replay cache
ndash have successfully used memcached for this in past
bull could have run memcached instances in Docker containers alongside IdPcontainers
ndash additional infrastructurecode to managemaintain
ndash memcached discovery problem as number of instances growshrink
bull offload memcached duties to AWS ElastiCache
ndash 3 x t2micro cache nodes (us-west-2) = ~$25mo (on-demand) or ~$13mo (reserved w 1 yrterm)
bull use AWSrsquo ElastiCache Cluster Java client [7]
ndash drop-in replacement for spymemcached jar
ndash supports ElastiCachersquos memcached auto-discovery enhancement
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 64 ]
Agility Decision 4 ndash use SAM for app password website
bull SAM = Serverless Application Model
ndash AWS specification for defining serverless applications in AWS
ndash built on top of existing AWS components like Lambda CloudFront and API Gateway
bull website is utility site ndash not used heavily but must always be accessible
bull written as SPA using AngularJS
ndash interacts with API written in Express (Nodejs application framework)
bull API deployed as Lambda function and exposed via API gateway
ndash Claudiajs used to deploy
bull Passportjs used for Shib authentication and session state stored in DynamoDB
bull use of Lambda + DynamoDB makes this solution essentially free for the amount of utilization we have
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 65 ]
Agility Decision 5 ndash use CloudFormation + Git
bull entire IdP environment specified and deployed via AWS CloudFormation
bull CloudFormation templates storedmaintained in git repository
bull changes to environment performed through CF change sets
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
[ 66 ]
[demo]
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks
Resources
bull [1] httpswikishibbolethnetconfluencedisplayIDP30ECPConfiguration
bull [2] httpsgithubcomJanOppolzerjaas-rdbms-hashed
bull [3] httpswikishibbolethnetconfluencedisplayIDP30MultiFactorAuthnConfiguration
bull [4] httpswikishibbolethnetconfluencedisplayIDP30DuoAuthnConfiguration
bull [5] httpsgithubcomUniconshibboleth-idp-dockerized
bull [6] httpsgithubcomUniconshibboleth-idp-dockerizedwikiSwitching-to-the-Oracle-JVM
bull [7] httpsgithubcomawslabsaws-elasticache-cluster-client-memcached-for-java
bull JAAS DynamoDB module httpsbitbucketorgua_siajaas-dynamodb
Thanks