Author: anil.saldhana(a)jboss.com
Date: 2011-02-07 22:51:59 -0500 (Mon, 07 Feb 2011)
New Revision: 744
Added:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/JBossAuthCacheInvalidationFactory.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/SecurityActions.java
Modified:
federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/bindings/jboss/auth/SAML2STSLoginModule.java
federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/bindings/jboss/auth/SecurityActions.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/util/AssertionUtil.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/auth/AbstractSTSLoginModule.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/plugins/saml/SAMLUtil.java
Log:
PLFED-132: register to expire the JBoss Auth Cache when saml principal expires
Modified:
federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/bindings/jboss/auth/SAML2STSLoginModule.java
===================================================================
---
federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/bindings/jboss/auth/SAML2STSLoginModule.java 2011-02-07
23:17:31 UTC (rev 743)
+++
federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/bindings/jboss/auth/SAML2STSLoginModule.java 2011-02-08
03:51:59 UTC (rev 744)
@@ -32,11 +32,16 @@
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
+import javax.xml.datatype.XMLGregorianCalendar;
+import org.jboss.security.SecurityConstants;
import org.jboss.security.auth.callback.ObjectCallback;
import org.jboss.security.auth.spi.AbstractServerLoginModule;
import org.picketlink.identity.federation.bindings.jboss.subject.PicketLinkGroup;
import org.picketlink.identity.federation.bindings.jboss.subject.PicketLinkPrincipal;
+import
org.picketlink.identity.federation.core.factories.JBossAuthCacheInvalidationFactory;
+import
org.picketlink.identity.federation.core.factories.JBossAuthCacheInvalidationFactory.TimeCacheExpiry;
+import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil;
import org.picketlink.identity.federation.core.wstrust.STSClient;
import org.picketlink.identity.federation.core.wstrust.STSClientConfig.Builder;
import org.picketlink.identity.federation.core.wstrust.SamlCredential;
@@ -59,11 +64,16 @@
* and included in the {@code Group} returned by the {@code getRoleSets} method.
* </p>
* <p>
- * This module defines one module option:
+ * This module defines module options:
* <li>
* <ul>configFile - this property identifies the properties file that will be used
to establish communication with
* the external security token service.
* </ul>
+ * <ul>cache.invalidation: set it to true if you require invalidation of JBoss
Auth Cache at SAML Principal expiration.
+ * </ul>
+ * <ul>jboss.security.security_domain: name of the security domain where this
login module is configured. This is only required
+ * if the cache.invalidation option is configured.
+ * </ul>
* </li>
* An example of a {@code configFile} can be seen bellow:
* <pre>
@@ -82,6 +92,7 @@
* </p>
*
* @author <a href="mailto:sguilhen@redhat.com">Stefan Guilhen</a>
+ * @author Anil.Saldhana(a)redhat.com
*/
@SuppressWarnings("unchecked")
public class SAML2STSLoginModule extends AbstractServerLoginModule
@@ -95,6 +106,10 @@
protected AssertionType assertion;
+ protected boolean enableCacheInvalidation = false;
+
+ protected String securityDomain = null;
+
/*
* (non-Javadoc)
* @see
org.jboss.security.auth.spi.AbstractServerLoginModule#initialize(javax.security.auth.Subject,
javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
@@ -106,6 +121,16 @@
super.initialize(subject, callbackHandler, sharedState, options);
// check if the options contain the name of the STS configuration file.
this.stsConfigurationFile = (String) options.get("configFile");
+
+ String cacheInvalidation = (String) options.get( "cache.invalidation" );
+ if( cacheInvalidation != null && !cacheInvalidation.isEmpty() )
+ {
+ enableCacheInvalidation = Boolean.parseBoolean( cacheInvalidation );
+ securityDomain = (String) options.get( SecurityConstants.SECURITY_DOMAIN_OPTION
);
+ if( securityDomain == null || securityDomain.isEmpty() )
+ throw new RuntimeException( "Please configure option:" +
SecurityConstants.SECURITY_DOMAIN_OPTION );
+ }
+
}
/*
@@ -191,17 +216,22 @@
{
NameIDType nameID = (NameIDType) baseID;
this.principal = new PicketLinkPrincipal(nameID.getValue());
- }
- /*for (JAXBElement<?> element : subject.getContent())
- {
- if (element.getDeclaredType().equals(NameIDType.class))
+ //If the user has configured cache invalidation of subject based on saml
token expiry
+ if( enableCacheInvalidation )
{
- NameIDType nameID = (NameIDType) element.getValue();
- this.principal = new PicketLinkPrincipal(nameID.getValue());
- break;
+ TimeCacheExpiry cacheExpiry =
JBossAuthCacheInvalidationFactory.getCacheExpiry();
+ XMLGregorianCalendar expiry = AssertionUtil.getExpiration( assertion
);
+ if( expiry != null )
+ {
+ cacheExpiry.register( securityDomain,
expiry.toGregorianCalendar().getTime() , principal );
+ }
+ else
+ {
+ log.warn( "SAML Assertion has been found to have no expiration:
ID = " + assertion.getID() );
+ }
}
- }*/
+ }
}
}
catch (Exception e)
Modified:
federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/bindings/jboss/auth/SecurityActions.java
===================================================================
---
federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/bindings/jboss/auth/SecurityActions.java 2011-02-07
23:17:31 UTC (rev 743)
+++
federation/trunk/picketlink-bindings-jboss/src/main/java/org/picketlink/identity/federation/bindings/jboss/auth/SecurityActions.java 2011-02-08
03:51:59 UTC (rev 744)
@@ -35,13 +35,12 @@
* @version $Revision: 1 $
*/
class SecurityActions
-{
- @SuppressWarnings({"rawtypes", "unchecked"})
+{
static SecurityContext createSecurityContext() throws PrivilegedActionException
{
- return (SecurityContext) AccessController.doPrivileged(new
PrivilegedExceptionAction()
+ return AccessController.doPrivileged(new
PrivilegedExceptionAction<SecurityContext>()
{
- public Object run() throws Exception
+ public SecurityContext run() throws Exception
{
return SecurityContextFactory.createSecurityContext("CLIENT");
}
Added:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/JBossAuthCacheInvalidationFactory.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/JBossAuthCacheInvalidationFactory.java
(rev 0)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/JBossAuthCacheInvalidationFactory.java 2011-02-08
03:51:59 UTC (rev 744)
@@ -0,0 +1,120 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.picketlink.identity.federation.core.factories;
+
+import java.security.Principal;
+import java.util.Date;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+/**
+ * <p>
+ * A factory that is used to obtain an expiration policy of type {@link TimeCacheExpiry}
+ * </p>
+ * <p>
+ * Primarily used to expire the SAML Principal in the JAAS Subject cached in the JBoss
Auth Cache.
+ * </p>
+ * @author Anil.Saldhana(a)redhat.com
+ * @since Feb 7, 2011
+ */
+public class JBossAuthCacheInvalidationFactory
+{
+ /**
+ * Get an instance of {@link TimeCacheExpiry}
+ * @return
+ */
+ public static TimeCacheExpiry getCacheExpiry()
+ {
+ return ExpiringPrincipalCacheInvalidation.get();
+ }
+
+ public interface TimeCacheExpiry
+ {
+ /**
+ * Register a Principal that has an expiry at {@link Date}
+ * @param securityDomain the security domain under which the principal may be
cached in a subject
+ * @param expiry when to expire the principal and hence the subject
+ * @param principal the principal which needs to be expired
+ */
+ void register( String securityDomain, Date expiry, Principal principal );
+ }
+
+ protected static class ExpiringPrincipalCacheInvalidation implements TimeCacheExpiry
+ {
+ protected static ExpiringPrincipalCacheInvalidation _instance = null;
+
+ protected static String objectName =
"jboss.security:service=JaasSecurityManager";
+
+ protected static Timer timer = new Timer();
+
+ protected ExpiringPrincipalCacheInvalidation()
+ {
+ }
+
+ protected static ExpiringPrincipalCacheInvalidation get()
+ {
+ if( _instance == null )
+ _instance = new ExpiringPrincipalCacheInvalidation();
+ return _instance;
+ }
+
+ protected static void setObjectName( String oName )
+ {
+ objectName = oName;
+ }
+
+ public void register( final String securityDomain, final Date expiry, final
Principal principal )
+ {
+ try
+ {
+ timer.schedule( new TimerTask()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ ObjectName on = new ObjectName( objectName );
+ MBeanServer server = SecurityActions.getJBossMBeanServer();
+ Object[] obj = new Object[] { securityDomain, principal };
+ String[] sig = new String[]{ "java.lang.String",
"java.security.Principal" };
+
+ //Flush the Authentication Cache
+ server.invoke( on,"flushAuthenticationCache", obj, sig );
+ }
+ catch ( Exception e)
+ {
+ throw new RuntimeException( e );
+ }
+ }
+ }, expiry );
+ }
+ catch ( Exception e )
+ {
+ throw new RuntimeException( e );
+ }
+ }
+ }
+}
\ No newline at end of file
Added:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/SecurityActions.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/SecurityActions.java
(rev 0)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/SecurityActions.java 2011-02-08
03:51:59 UTC (rev 744)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.picketlink.identity.federation.core.factories;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+
+import org.jboss.security.SecurityContext;
+import org.jboss.security.SecurityContextFactory;
+
+/**
+ * Privileged blocks
+ *
+ * @author <a href="mmoyses(a)redhat.com">Marcus Moyses</a>
+ * @version $Revision: 1 $
+ */
+class SecurityActions
+{
+ static SecurityContext createSecurityContext() throws PrivilegedActionException
+ {
+ return AccessController.doPrivileged(new
PrivilegedExceptionAction<SecurityContext>()
+ {
+ public SecurityContext run() throws Exception
+ {
+ return SecurityContextFactory.createSecurityContext("CLIENT");
+ }
+ });
+ }
+
+ static MBeanServer getJBossMBeanServer()
+ {
+ return AccessController.doPrivileged( new PrivilegedAction<MBeanServer>()
+ {
+ public MBeanServer run()
+ {
+ return MBeanServerFactory.findMBeanServer( "jboss").get( 0 );
+ }
+ });
+
+ }
+}
\ No newline at end of file
Property changes on:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/factories/SecurityActions.java
___________________________________________________________________
Name: svn:executable
+ *
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/util/AssertionUtil.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/util/AssertionUtil.java 2011-02-07
23:17:31 UTC (rev 743)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/saml/v2/util/AssertionUtil.java 2011-02-08
03:51:59 UTC (rev 744)
@@ -161,4 +161,21 @@
//TODO: if conditions do not exist, assume the assertion to be everlasting?
return false;
}
+
+ /**
+ * Extract the expiration time from an {@link AssertionType}
+ * @param assertion
+ * @return
+ */
+ public static XMLGregorianCalendar getExpiration( AssertionType assertion )
+ {
+ XMLGregorianCalendar expiry = null;
+
+ ConditionsType conditionsType = assertion.getConditions();
+ if(conditionsType != null)
+ {
+ expiry = conditionsType.getNotOnOrAfter();
+ }
+ return expiry;
+ }
}
\ No newline at end of file
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/auth/AbstractSTSLoginModule.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/auth/AbstractSTSLoginModule.java 2011-02-07
23:17:31 UTC (rev 743)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/auth/AbstractSTSLoginModule.java 2011-02-08
03:51:59 UTC (rev 744)
@@ -34,8 +34,10 @@
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
+import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.log4j.Logger;
+import org.jboss.security.SecurityConstants;
import org.jboss.security.SecurityContext;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
@@ -45,12 +47,17 @@
import org.jboss.security.mapping.MappingManager;
import org.jboss.security.mapping.MappingType;
import org.picketlink.identity.federation.core.exceptions.ParsingException;
+import
org.picketlink.identity.federation.core.factories.JBossAuthCacheInvalidationFactory;
+import
org.picketlink.identity.federation.core.factories.JBossAuthCacheInvalidationFactory.TimeCacheExpiry;
+import org.picketlink.identity.federation.core.saml.v2.util.AssertionUtil;
import org.picketlink.identity.federation.core.wstrust.STSClient;
import org.picketlink.identity.federation.core.wstrust.STSClientConfig;
import org.picketlink.identity.federation.core.wstrust.STSClientConfig.Builder;
import org.picketlink.identity.federation.core.wstrust.STSClientFactory;
import org.picketlink.identity.federation.core.wstrust.SamlCredential;
import org.picketlink.identity.federation.core.wstrust.WSTrustException;
+import org.picketlink.identity.federation.core.wstrust.plugins.saml.SAMLUtil;
+import org.picketlink.identity.federation.newmodel.saml.v2.assertion.AssertionType;
import org.w3c.dom.Element;
/**
@@ -143,7 +150,12 @@
* from "Roles".
* </p>
*
+ * <p>cache.invalidation: set it to true if you require invalidation of JBoss Auth
Cache at SAML Principal expiration.</p>
+ * <p>jboss.security.security_domain: name of the security domain where this login
module is configured. This is only required
+ * if the cache.invalidation option is configured.</p>
+ *
* @author <a href="mailto:dbevenius@jboss.com">Daniel
Bevenius</a>
+ * @author Anil.Saldhana(a)redhat.com
*/
public abstract class AbstractSTSLoginModule implements LoginModule
{
@@ -225,6 +237,10 @@
* Name of the group principal. If unconfigured, will be "null"
*/
protected String groupPrincipalName = null;
+
+ protected boolean enableCacheInvalidation = false;
+
+ protected String securityDomain = null;
/**
* Initialized this login module. Simple stores the passed in fields and
@@ -261,6 +277,15 @@
final String gpPrincipalName = (String) options.get( GROUP_PRINCIPAL_NAME );
if( gpPrincipalName != null && gpPrincipalName.length() > 0 )
groupPrincipalName = gpPrincipalName;
+
+ String cacheInvalidation = (String) options.get( "cache.invalidation" );
+ if( cacheInvalidation != null && !cacheInvalidation.isEmpty() )
+ {
+ enableCacheInvalidation = Boolean.parseBoolean( cacheInvalidation );
+ securityDomain = (String) options.get( SecurityConstants.SECURITY_DOMAIN_OPTION
);
+ if( securityDomain == null || securityDomain.isEmpty() )
+ throw new RuntimeException( "Please configure option:" +
SecurityConstants.SECURITY_DOMAIN_OPTION );
+ }
}
/**
@@ -573,6 +598,30 @@
principalMappingContext.performMapping(contextMap, null);
Principal principal =
principalMappingContext.getMappingResult().getMappedObject();
subject.getPrincipals().add(principal);
+
+ //If the user has configured cache invalidation of subject based on saml token
expiry
+ if( enableCacheInvalidation )
+ {
+ TimeCacheExpiry cacheExpiry =
JBossAuthCacheInvalidationFactory.getCacheExpiry();
+ AssertionType assertion = null;
+ try
+ {
+ assertion = SAMLUtil.fromElement( samlToken );
+ }
+ catch ( Exception e)
+ {
+ throw new RuntimeException( e );
+ }
+ XMLGregorianCalendar expiry = AssertionUtil.getExpiration( assertion );
+ if( expiry != null )
+ {
+ cacheExpiry.register( securityDomain,
expiry.toGregorianCalendar().getTime() , principal );
+ }
+ else
+ {
+ log.warn( "SAML Assertion has been found to have no expiration: ID =
" + assertion.getID() );
+ }
+ }
}
if (roleMappingContext != null)
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/plugins/saml/SAMLUtil.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/plugins/saml/SAMLUtil.java 2011-02-07
23:17:31 UTC (rev 743)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/wstrust/plugins/saml/SAMLUtil.java 2011-02-08
03:51:59 UTC (rev 744)
@@ -24,8 +24,6 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import javax.xml.bind.JAXBException;
-
import org.picketlink.identity.federation.core.exceptions.ConfigurationException;
import org.picketlink.identity.federation.core.exceptions.ParsingException;
import org.picketlink.identity.federation.core.exceptions.ProcessingException;
@@ -100,12 +98,11 @@
* @param assertionElement
* the {@code Element} that contains the marshaled SAMLV2.0 assertion.
* @return a reference to the unmarshaled {@code AssertionType} instance.
- * @throws JAXBException if an error occurs while unmarshalling the document.
* @throws ConfigurationException
* @throws ProcessingException
* @throws ParsingException
*/
- public static AssertionType fromElement(Element assertionElement) throws
JAXBException, ProcessingException, ConfigurationException, ParsingException
+ public static AssertionType fromElement(Element assertionElement) throws
ProcessingException, ConfigurationException, ParsingException
{
String assertionAsString = DocumentUtil.getDOMElementAsString(assertionElement);