[jboss-svn-commits] JBL Code SVN: r23518 - in labs/jbossesb/branches/JBESB_4_4_GA_CP/product: install/conf and 11 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Oct 20 05:08:17 EDT 2008
Author: beve
Date: 2008-10-20 05:08:16 -0400 (Mon, 20 Oct 2008)
New Revision: 23518
Added:
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/CryptoUtilUnitTest.java
Modified:
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/docs/ServicesGuide.odt
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/docs/ServicesGuide.pdf
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/install/conf/jbossesb-properties.xml
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtil.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/client/ServiceInvoker.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Configuration.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Environment.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipeline.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/PublicCryptoUtil.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/SecurityContext.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/auth/AuthenticationRequestImpl.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/util/CryptoUtil.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/JaasSecurityServiceUnitTest.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtilUnitTest.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/security-properties.xml
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipelineUnitTest.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/security-properties.xml
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/PublicCryptoUtilUnitTest.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/SecurityContextUnitTest.java
labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/security-properties.xml
Log:
Work for https://jira.jboss.org/jira/browse/JBESB-2121 "Replace crypto util with sealed object"
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/docs/ServicesGuide.odt
===================================================================
(Binary files differ)
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/docs/ServicesGuide.pdf
===================================================================
(Binary files differ)
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/install/conf/jbossesb-properties.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/install/conf/jbossesb-properties.xml 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/install/conf/jbossesb-properties.xml 2008-10-20 09:08:16 UTC (rev 23518)
@@ -40,13 +40,15 @@
<properties name="security">
<property name="org.jboss.soa.esb.services.security.implementationClass" value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>
<property name="org.jboss.soa.esb.services.security.callbackHandler" value="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
+
+ <!-- Algorithm and key size for internal sealing of objects -->
+ <property name="org.jboss.soa.esb.services.security.sealAlgorithm" value="TripleDES"/>
+ <property name="org.jboss.soa.esb.services.security.sealKeySize" value="168"/>
+
+ <!-- Timeout in milliseconds. After which the context is considered invalid -->
+ <property name="org.jboss.soa.esb.services.security.contextTimeout" value="30000"/>
- <property name="org.jboss.soa.esb.services.security.privateKeystore" value="/privateKeyStore"/>
- <property name="org.jboss.soa.esb.services.security.privateKeystorePassword" value="testKeystorePassword"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyAlias" value="testAlias"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyPassword" value="testPassword"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyTransformation" value="RSA/ECB/PKCS1Padding"/>
-
+ <!-- Public keystore configuration used to hold keys for encryption/decryption -->
<property name="org.jboss.soa.esb.services.security.publicKeystore" value="/publicKeyStore"/>
<property name="org.jboss.soa.esb.services.security.publicKeystorePassword" value="testKeystorePassword"/>
<property name="org.jboss.soa.esb.services.security.publicKeyAlias" value="testAlias"/>
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtil.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtil.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtil.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -20,50 +20,42 @@
*/
package org.jboss.internal.soa.esb.services.security;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
import java.io.Serializable;
-import java.security.Key;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
+import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.UnrecoverableKeyException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SealedObject;
+import javax.crypto.SecretKey;
import org.apache.log4j.Logger;
+import org.jboss.internal.soa.esb.assertion.AssertArgument;
import org.jboss.soa.esb.common.Configuration;
import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.services.security.SecurityServiceException;
-import org.jboss.soa.esb.services.security.util.CryptoUtil;
-import org.jboss.soa.esb.util.ClassUtil;
/**
+ * Util for sealing and unsealing object.
*
* @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
- *
*/
public enum PrivateCryptoUtil
{
INSTANCE;
private Logger log;
- private Key key;
- private PublicKey publicKey;
- private String transformation;
+ private Cipher cipher;
+ private SecretKey secretKey;
private PrivateCryptoUtil()
{
try
{
log = getLogger();
- init();
+ initSecretKey();
}
catch (final Exception e)
{
@@ -71,189 +63,130 @@
}
}
- private void init() throws SecurityServiceException
+ /**
+ * Will create a Sealed object containing the passed in Serializable object.
+ *
+ * @param serializable The serializable object to be sealed.
+ * @return SealedObject The resulting sealed object
+ * @throws SecurityServiceException
+ * @throws IOException
+ * @throws IllegalBlockSizeException
+ */
+ public SealedObject sealObject(final Serializable serializable) throws SecurityServiceException
{
- String keystorePath = Configuration.getSecurityServicePrivateKeystore();
- if (keystorePath == null)
+ AssertArgument.isNotNull(serializable, "serializable");
+ try
{
- log.info("No private keystore was specified in jbossesb-properites.xml. Add '" + Environment.SECURITY_SERVICE_PUBLIC_KEYSTORE + "'");
- }
- else
- {
- try
+ synchronized (cipher)
{
- String keystoreType = Configuration.getSecurityServicePrivateKeystoreType();
- if (keystoreType == null)
- {
- keystoreType = KeyStore.getDefaultType();
- }
- String keystorePassword = Configuration.getSecurityServicePrivateKeystorePassword();
- String privateKeyAlias = Configuration.getSecurityServicePrivateKeyAlias();
- String privateKeyPass = Configuration.getSecurityServicePrivateKeyPassword();
-
- try
- {
- KeyStore keystore = KeyStore.getInstance(keystoreType);
- InputStream in = ClassUtil.getResourceAsStream(keystorePath, this.getClass());
- if (in == null)
- {
- throw new SecurityServiceException("Could not locate public keystore using '" + keystorePath + "'");
- }
-
- // load the keystore contents
- keystore.load(in, keystorePassword.toCharArray());
- key = keystore.getKey(privateKeyAlias, privateKeyPass.toCharArray());
- Certificate certificate = keystore.getCertificate(privateKeyAlias);
- publicKey = certificate.getPublicKey();
-
- // "algorithm/mode/padding" or defaults to "algorithm"
- transformation = Configuration.getSecurityServicePrivateKeyTransformation();
- if (transformation == null)
- {
- this.transformation = key.getAlgorithm();
- }
- }
- finally
- {
- keystorePassword = null;
- privateKeyAlias = null;
- privateKeyPass = null;
- }
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);;
+ return new SealedObject(serializable, cipher);
}
- catch (final KeyStoreException e)
- {
- throw new SecurityServiceException(e.getMessage(), e);
- }
- catch (final NoSuchAlgorithmException e)
- {
- throw new SecurityServiceException(e.getMessage(), e);
- }
- catch (final CertificateException e)
- {
- throw new SecurityServiceException(e.getMessage(), e);
- }
- catch (final IOException e)
- {
- throw new SecurityServiceException(e.getMessage(), e);
- }
- catch (final UnrecoverableKeyException e)
- {
- throw new SecurityServiceException(e.getMessage(), e);
- }
}
- }
-
- private static byte[] getBytes(final Serializable ser) throws IOException
- {
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- ObjectOutputStream oout = new ObjectOutputStream(bout);
- oout.writeObject(ser);
- return bout.toByteArray();
- }
-
- public byte[] encrypt(final Serializable object) throws SecurityServiceException
- {
- ByteArrayInputStream plainInStream;
- try
+ catch (final InvalidKeyException e)
{
- plainInStream = new ByteArrayInputStream(getBytes(object));
+ throw new SecurityServiceException(e.getMessage(), e);
}
- catch (final IOException e)
+ catch (final IllegalBlockSizeException e)
{
throw new SecurityServiceException(e.getMessage(), e);
}
-
- ByteArrayOutputStream encryptedOutStream = new ByteArrayOutputStream();
-
- try
- {
- byte[] buf = new byte[100];
- int bufLength;
- while ( (bufLength = plainInStream.read(buf)) != -1)
- {
- byte[] tmp = CryptoUtil.encrypt(copyBytes(buf,bufLength),publicKey, transformation);
- encryptedOutStream.write(tmp);
- encryptedOutStream.flush();
- }
- return encryptedOutStream.toByteArray();
- }
catch (final IOException e)
{
throw new SecurityServiceException(e.getMessage(), e);
}
}
- public Serializable decrypt(final byte[] bytes) throws SecurityServiceException
+ /**
+ * Unseals a previously sealed object.
+ *
+ * @param sealedObject The object to unseal
+ * @return {@link Serializable} The unsealed Serializeable Object.
+ * @throws SecurityServiceException
+ */
+ public Serializable unSealObject(SealedObject sealedObject) throws SecurityServiceException
{
- ByteArrayInputStream encryptedBytesInStream = new ByteArrayInputStream(bytes);
-
- ByteArrayOutputStream decryptedBytesOutStream = new ByteArrayOutputStream();
-
- byte[] decryptBytes = null;
+ AssertArgument.isNotNull(sealedObject, "sealedObject");
try
{
- byte[] buf = new byte[128];
- int bufLenth;
- while ( (bufLenth = encryptedBytesInStream.read(buf)) != -1)
+ synchronized (cipher)
{
- byte[] tmp = CryptoUtil.decrypt( copyBytes(buf,bufLenth),(PrivateKey)key, transformation);
- decryptedBytesOutStream.write(tmp);
- decryptedBytesOutStream.flush();
- decryptBytes = decryptedBytesOutStream.toByteArray();
+ cipher.init(Cipher.DECRYPT_MODE, secretKey);
+ return (Serializable) sealedObject.getObject(cipher);
}
}
- catch (final IOException e)
+ catch (final InvalidKeyException e)
{
throw new SecurityServiceException(e.getMessage(), e);
}
- finally
+ catch (final IllegalBlockSizeException e)
{
- try { decryptedBytesOutStream.close(); } catch (IOException ignore) { log.error(ignore.getMessage(),ignore); }
+ throw new SecurityServiceException(e.getMessage(), e);
}
-
- return toSerializable(decryptBytes);
- }
-
- private Serializable toSerializable(final byte[] decryptBytes) throws SecurityServiceException
- {
- ObjectInputStream inputStream = null;
- try
+ catch (final BadPaddingException e)
{
- inputStream = new ObjectInputStream(new ByteArrayInputStream(decryptBytes));
- return (Serializable) inputStream.readObject();
+ throw new SecurityServiceException(e.getMessage(), e);
}
- catch (final IOException e)
+ catch (IOException e)
{
throw new SecurityServiceException(e.getMessage(), e);
}
- catch (final ClassNotFoundException e)
+ catch (ClassNotFoundException e)
{
throw new SecurityServiceException(e.getMessage(), e);
}
- finally
- {
- try { inputStream.close(); } catch (IOException ignore) { log.error(ignore.getMessage(), ignore); }
- }
}
- private static byte[] copyBytes(byte[] bytes, int length)
+ /**
+ * Generates a symmetric key used for sealing object.
+ *
+ * @throws SecurityServiceException
+ */
+ private void initSecretKey() throws SecurityServiceException
{
- if (bytes.length == length)
+ try
{
- return bytes;
- }
+ final String algorithm = Configuration.getSecurityServiceSealAlgorithm();
+ if (algorithm == null)
+ {
+ throw new SecurityServiceException("'" + Environment.SECURITY_SERVICE_SEAL_ALGORITHM + "' has not been configured. Please set the algorithm to use in jbossesb-properties.xml");
+ }
- byte[] newBytes = new byte[length];
- for (int i = 0; i < length; i++)
+ final String keySizeStr = Configuration.getSecurityServiceSealKeySize();
+ if (keySizeStr == null)
+ {
+ throw new SecurityServiceException("'" + Environment.SECURITY_SERVICE_SEAL_KEYSIZE + "' has not been configured. Please set the key size to use in jbossesb-properties.xml");
+ }
+
+ int keySize;
+ try
+ {
+ keySize = Integer.parseInt(keySizeStr.trim());
+ }
+ catch(final NumberFormatException e)
+ {
+ throw new SecurityServiceException("'" + Environment.SECURITY_SERVICE_SEAL_KEYSIZE + "' must be a number. Please set the key size correctly in jbossesb-properties.xml");
+ }
+
+ log.debug("SealAlgorithm '" + algorithm + "' keySize '" + keySize + "'");
+
+ final KeyGenerator kpg = KeyGenerator.getInstance(algorithm);
+ kpg.init(keySize);
+ secretKey = kpg.generateKey();
+ cipher = Cipher.getInstance(algorithm);
+ }
+ catch (final NoSuchAlgorithmException e)
{
- newBytes[i] = bytes[i];
+ throw new SecurityServiceException(e.getMessage(), e);
}
- return newBytes;
+ catch (final NoSuchPaddingException e)
+ {
+ throw new SecurityServiceException(e.getMessage(), e);
+ }
}
private static Logger getLogger()
{
return Logger.getLogger(PrivateCryptoUtil.class);
}
-
}
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/client/ServiceInvoker.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/client/ServiceInvoker.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/client/ServiceInvoker.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -19,18 +19,15 @@
*/
package org.jboss.soa.esb.client;
-import java.security.AccessController;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.crypto.SealedObject;
-import javax.security.auth.Subject;
import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.addressing.helpers.EPRHelper;
import org.jboss.internal.soa.esb.assertion.AssertArgument;
-import org.jboss.internal.soa.esb.services.security.PrivateCryptoUtil;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.Service;
import org.jboss.soa.esb.addressing.EPR;
@@ -43,9 +40,9 @@
import org.jboss.soa.esb.couriers.Courier;
import org.jboss.soa.esb.couriers.CourierException;
import org.jboss.soa.esb.couriers.CourierFactory;
+import org.jboss.soa.esb.couriers.CourierMarshalUnmarshalException;
+import org.jboss.soa.esb.couriers.CourierServiceBindException;
import org.jboss.soa.esb.couriers.CourierTransportException;
-import org.jboss.soa.esb.couriers.CourierServiceBindException;
-import org.jboss.soa.esb.couriers.CourierMarshalUnmarshalException;
import org.jboss.soa.esb.couriers.CourierUtil;
import org.jboss.soa.esb.couriers.FaultMessageException;
import org.jboss.soa.esb.couriers.TwoWayCourier;
@@ -63,7 +60,7 @@
import org.jboss.soa.esb.services.registry.ServiceNotFoundException;
import org.jboss.soa.esb.services.security.SecurityContext;
import org.jboss.soa.esb.services.security.SecurityService;
-import org.jboss.soa.esb.services.security.SecurityServiceException;
+import org.jboss.soa.esb.services.security.auth.AuthenticationRequestImpl;
import org.jboss.soa.esb.util.ClassUtil;
/**
@@ -290,6 +287,28 @@
private Message post(Message message, EPRInvoker eprInvoker) throws MessageDeliverException, FaultMessageException {
boolean staleEPRCache = true;
boolean initialPass = true;
+
+ /*
+ * Re-attach encrypted SecurityContext to outgoing message.
+ */
+ final SealedObject sealedObject = SecurityContext.getSecurityContext();
+ if (sealedObject != null)
+ {
+ message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
+ // clear the security context from the thread local.
+ SecurityContext.setSecurityContext(null);
+ }
+ /*
+ * Re-attach encrypted AuthenticationRequest to outgoing message.
+ */
+ final byte[] encryptedAuthRequest = AuthenticationRequestImpl.getEncryptedAuthRequest();
+ if (encryptedAuthRequest != null)
+ {
+ message.getContext().setContext(SecurityService.AUTH_REQUEST, encryptedAuthRequest);
+ // clear the auth request from the thread local.
+ AuthenticationRequestImpl.setEncryptedAuthRequest(null);
+ }
+
//We are removing dead EPRs from the serviceClusterInfo. *Previous* deliveries maybe have
//removed EPRs that have now come back to life. We should try once more to pull a fresh list of EPRS
//from the registry before we give up (and fail-over to redelivery at a later time in the care
@@ -323,25 +342,11 @@
while ((epr = loadBalancer.chooseEPR(serviceClusterInfo)) != null) {
try
{
- final Subject subject = Subject.getSubject(AccessController.getContext());
- if (subject != null)
- {
- logger.info("Subject in ServiceInvoker " + subject);
- try
- {
- byte[] encrypted = PrivateCryptoUtil.INSTANCE.encrypt(new SecurityContext(subject));
- message.getContext().setContext(SecurityService.CONTEXT, encrypted);
- }
- catch (final SecurityServiceException e)
- {
- logger.error("Could not encrypt the security conext. Will not be added to the outgoing message", e);
- }
- }
-
replyMessage = eprInvoker.attemptDelivery(message, epr);
if (replyMessage != null) {
// remove the security context so that it is not exposed to the action pipeline.
replyMessage.getContext().removeContext(SecurityService.CONTEXT);
+ replyMessage.getContext().removeContext(SecurityService.AUTH_REQUEST);
if (Type.isFaultMessage(replyMessage)) {
Factory.createExceptionFromFault(replyMessage) ;
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Configuration.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Configuration.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Configuration.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -534,6 +534,21 @@
return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperty(Environment.SECURITY_SERVICE_CALLBACK_HANLDER_CLASS);
}
+ public static String getSecurityServiceSealAlgorithm()
+ {
+ return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperty(Environment.SECURITY_SERVICE_SEAL_ALGORITHM);
+ }
+
+ public static String getSecurityServiceSealKeySize()
+ {
+ return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperty(Environment.SECURITY_SERVICE_SEAL_KEYSIZE);
+ }
+
+ public static String getSecurityServiceContextTimeout()
+ {
+ return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperty(Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT);
+ }
+
public static Properties getSecurityServiceProperies()
{
return ModulePropertyManager.getPropertyManager(ModulePropertyManager.SECURITY_MODULE).getProperties();
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Environment.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Environment.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/common/Environment.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -230,6 +230,7 @@
public static final String SECURITY_SERVICE_CONFIG_URL = "org.jboss.soa.esb.services.security.configUrl";
public static final String SECURITY_SERVICE_SEAL_ALGORITHM = "org.jboss.soa.esb.services.security.sealAlgorithm";
public static final String SECURITY_SERVICE_SEAL_KEYSIZE = "org.jboss.soa.esb.services.security.sealKeySize";
+ public static final String SECURITY_SERVICE_CONTEXT_TIMEOUT = "org.jboss.soa.esb.services.security.contextTimeout";
public static final String SECURITY_SERVICE_PRIVATE_KEYSTORE = "org.jboss.soa.esb.services.security.privateKeystore";
public static final String SECURITY_SERVICE_PRIVATE_KEYSTORE_TYPE = "org.jboss.soa.esb.services.security.privateKeystoreType";
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipeline.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipeline.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipeline.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -22,10 +22,12 @@
package org.jboss.soa.esb.listeners.message;
+import java.net.URISyntaxException;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
+import javax.crypto.SealedObject;
import javax.security.auth.Subject;
import javax.xml.validation.Schema;
@@ -43,6 +45,7 @@
import org.jboss.soa.esb.addressing.util.DefaultFaultTo;
import org.jboss.soa.esb.addressing.util.DefaultReplyTo;
import org.jboss.soa.esb.client.ServiceInvoker;
+import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.couriers.Courier;
import org.jboss.soa.esb.couriers.CourierException;
import org.jboss.soa.esb.couriers.CourierFactory;
@@ -62,6 +65,7 @@
import org.jboss.soa.esb.services.security.SecurityServiceException;
import org.jboss.soa.esb.services.security.SecurityServiceFactory;
import org.jboss.soa.esb.services.security.auth.AuthenticationRequest;
+import org.jboss.soa.esb.services.security.auth.AuthenticationRequestImpl;
import org.jboss.soa.esb.util.ClassUtil;
import org.xml.sax.SAXException;
@@ -71,6 +75,7 @@
* @author <a
* href="mailto:schifest at heuristica.com.ar">schifest at heuristica.com.ar</a>
* @author kevin
+ * @author <a href="mailto:dbevenius at jboss.com">Daniel Bevenius</a>
* @since Version 4.0
*/
public class ActionProcessingPipeline
@@ -367,32 +372,11 @@
LOGGER.debug("pipeline process for message: "+message.getHeader());
}
- SecurityContext securityContext = null;
- try
- {
- // Check if a encrypted SecurityContext was passed with the Message to this service.
- securityContext = SecurityContext.decryptContext((byte[])message.getContext().getContext(SecurityService.CONTEXT));
- }
- catch (final SecurityServiceException e)
- {
- LOGGER.debug("Security exception: ", e);
- // just make sure the securityContext is null. This will trigger a new auth if security is enabled.
- securityContext = null;
- }
-
- if (securityConf != null || securityContext != null)
- {
- return processPipelineSecured(message, securityContext);
- }
- else
- {
- return processPipeline(message);
- }
+ return processPipeline(message, getSecurityContext(message));
}
else
{
- final Call callDetails = new Call() ;
- callDetails.copy(message.getHeader().getCall()) ;
+ final Call callDetails = createCallDetails(message);
LOGGER.debug("pipeline process disabled for message: "+message.getHeader());
faultTo(callDetails, Factory.createErrorMessage(Factory.NOT_ENABLED, message, null));
@@ -404,40 +388,95 @@
}
}
- private boolean processPipelineSecured(final Message message, SecurityContext securityContext)
+ /**
+ * Processes the action pipeline.
+ * <p/>
+ * If the service has been enable for security authentication, it has the security element
+ * in the configuration xml that is, this method will authenitcate the caller.
+ * If security has not been enabled this method will not perform any authentication but
+ * it will pass through a pre-existing SecurityContext.
+ * <p>
+ * <h1>SecurityContext</h1>
+ * After the caller has been successfully authenticated a SecurityContext will be created.
+ * This context is valid on the current ESB node(VM) only. When a SecurityContext is created
+ * a timeout is specified. This value can either be the globally value specified in jbossesb-properties.xml
+ * or it can be overridden per service by specifiying the same property in the security element in jboss-esb.xml:
+ * The value is specified in milliseconds.
+ * <pre>
+ * <security module="someModuleName">
+ * <property name="org.jboss.soa.esb.services.security.contextTimeout" value="50000"/>
+ * </security>
+ * </pre>
+ * <h1>AuthenticationRequest</h1>
+ * If a call is routed to a different ESB node then that node will re-authenticate the call.
+ * The node will descrypt the authentication request passed with the Message object
+ * and try to authenticate the caller.
+ *
+ * @param message The ESB message object.
+ * @param sealedSecurityContext The sealed SecurityContext which will exist if the caller has already been authenticated.
+ * @return true If the action pipeline was processed successfully.
+ */
+ private boolean processPipeline(final Message message, final SealedObject sealedSecurityContext)
{
- final Call callDetails = new Call() ;
- callDetails.copy(message.getHeader().getCall()) ;
+ SecurityContext securityContext = null;
+ if (sealedSecurityContext != null )
+ {
+ // store the security context. Will be re-attached to outgoing messages regardless whether the service is secured or not.
+ SecurityContext.setSecurityContext(sealedSecurityContext);
+ }
+
try
{
- // always perform authentication if the service is security enabled.
- if (securityConf != null )
+ if (isServiceSecured())
{
- if (securityContext == null)
+ try // to decrypt the security context.
+ {
+ securityContext = SecurityContext.decryptContext(sealedSecurityContext);
+ }
+ catch (final SecurityServiceException ignored)
+ {
+ LOGGER.debug("Could not decrypt the security context. Might have come from a different VM. Will re-authenticate if security is enabled for this service.", ignored);
+ securityContext = null;
+ }
+
+ if (LOGGER.isDebugEnabled())
+ {
+ if (securityContext != null)
+ {
+ /*
+ * Might be interesting to know if a security context is often invalid as this
+ * will cause re-authentication. This might be avoidable by setting a longer
+ * timeout by overriding the default timeout(jbossesb-properties.xml) and specifying
+ * one on the security element in jboss-esb.xml.
+ */
+ LOGGER.debug(securityContext);
+ }
+ }
+
+ final SecurityService securityService = SecurityServiceFactory.getSecurityService();
+
+ if (securityContext == null || !securityContext.isValid())
{
- // no existing security context exist. Create one to drive the autentication.
- securityContext = new SecurityContext();
+ // get the encrypted AuthenticationRequest from the message
+ final byte[] encryptedAuthRequest = getAutenticationRequest(message);
+ final AuthenticationRequest authRequest = (AuthenticationRequest) PublicCryptoUtil.INSTANCE.decrypt(encryptedAuthRequest);
- // get the authentication request from the message
- byte[] encrypted = (byte[]) message.getContext().getContext(SecurityService.AUTH_REQUEST);
- if (encrypted == null)
- {
- throw new SecurityServiceException("Missing AuthenticationRequest. Cannot be authenticated.");
- }
- AuthenticationRequest authRequest = (AuthenticationRequest) PublicCryptoUtil.INSTANCE.decrypt(encrypted);
+ // store the encrypted auth request. Will be re-attached to outgoing messages.
+ AuthenticationRequestImpl.setEncryptedAuthRequest(encryptedAuthRequest);
- // authenticate the caller
- SecurityServiceFactory.getSecurityService().authenticate(securityConf, securityContext, authRequest);
+ // no existing security context exist or it had expired. Create a new one to drive the autentication.
+ securityContext = new SecurityContext(new Subject(), getSecurityContextTimeout(securityConf));
+
+ // authenticate the caller
+ securityService.authenticate(securityConf, securityContext, authRequest);
+
+ // store the encrypted security context. Will be re-attached to outgoing messages.
+ SecurityContext.setSecurityContext(SecurityContext.encryptContext(securityContext));
}
- /*
- * The SecurityContext was not null so we were able to decrypt the security context
- * and this is a valid authenticated request and re-authentication is not done.
- */
- // check the allowed roles if configured.
- boolean checkRolesAllowed = SecurityServiceFactory.getSecurityService().checkRolesAllowed(securityConf.getRolesAllowed(), securityContext);
- if (!checkRolesAllowed)
+ // check that the caller is a member of atleast on of the declared roles.
+ if (!securityService.checkRolesAllowed(securityConf.getRolesAllowed(), securityContext))
{
throw new SecurityServiceException("Caller did not belong to any of the rolesAllowed " + securityConf.getRolesAllowed());
}
@@ -445,14 +484,14 @@
}
catch (final SecurityServiceException e)
{
- LOGGER.debug( "SecurityService exception : ", e);
- faultTo(callDetails, Factory.createErrorMessage(Factory.UNEXPECTED_ERROR, message, e));
+ LOGGER.error( "SecurityService exception : ", e);
+ faultTo(createCallDetails(message), Factory.createErrorMessage(Factory.UNEXPECTED_ERROR, message, e));
return false;
}
catch (final ConfigurationException e)
{
- LOGGER.debug( "SecurityService exception : ", e);
- faultTo(callDetails, Factory.createErrorMessage(Factory.UNEXPECTED_ERROR, message, e));
+ LOGGER.error( "SecurityService exception : ", e);
+ faultTo(createCallDetails(message), Factory.createErrorMessage(Factory.UNEXPECTED_ERROR, message, e));
return false;
}
finally
@@ -462,25 +501,20 @@
message.getContext().removeContext(SecurityService.AUTH_REQUEST);
}
- // the work to be performed in the context of the authenticated caller
- PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>()
+ if (securityContext != null)
{
- public Boolean run()
- {
- return processPipeline(message);
- }
- };
-
- Boolean processResult = (Boolean)Subject.doAsPrivileged(securityContext.getSubject(), action, null);
-
- return processResult.booleanValue();
+ return (Boolean) Subject.doAsPrivileged(securityContext.getSubject(), getPrivilegedAction(message), null);
+ }
+ else
+ {
+ return processPipeline(message);
+ }
}
private boolean processPipeline(final Message message)
{
final long start = System.nanoTime();
- final Call callDetails = new Call() ;
- callDetails.copy(message.getHeader().getCall()) ;
+ final Call callDetails = createCallDetails(message);
if (LOGGER.isDebugEnabled())
{
@@ -836,4 +870,79 @@
}
}
+ private boolean isServiceSecured()
+ {
+ return securityConf != null;
+ }
+
+ private byte[] getAutenticationRequest(final Message message) throws SecurityServiceException
+ {
+ final byte[] encryptedAuthRequest = (byte[]) message.getContext().getContext(SecurityService.AUTH_REQUEST);
+ if (encryptedAuthRequest == null)
+ {
+ throw new SecurityServiceException("Missing AuthenticationRequest. Cannot be authenticated.");
+ }
+ return encryptedAuthRequest;
+ }
+
+ private SealedObject getSecurityContext(final Message message)
+ {
+ return (SealedObject) message.getContext().getContext(SecurityService.CONTEXT);
+ }
+
+ private PrivilegedAction<Boolean> getPrivilegedAction(final Message message)
+ {
+ // the work to be performed in the context of the authenticated caller
+ return new PrivilegedAction<Boolean>()
+ {
+ public Boolean run()
+ {
+ return processPipeline(message);
+ }
+ };
+ }
+
+ @SuppressWarnings("deprecation")
+ private Call createCallDetails(final Message message)
+ {
+ Call callDetails;
+ try
+ {
+ callDetails = new Call(message.getHeader().getCall());
+ }
+ catch (final URISyntaxException e)
+ {
+ LOGGER.error("Caught an URISyntaxException while calling Call's copy constructor. Will revert to using the old way using the copy method.", e);
+ callDetails = new Call();
+ callDetails.copy(message.getHeader().getCall()) ;
+ }
+ return callDetails;
+ }
+
+ /**
+ * Checks if the security config as a property named 'org.jboss.soa.esb.services.security.contextTimeout'
+ * specified. This will in that case be used as the SecurityContext timeout for this pipeline.
+ * If not specified the value will fallback to the value specified in jbossesb-properties.xml
+ *
+ * @param securityConfig The security configuration for this pipeline. This maps to the security element in jboss-esb.xml
+ * @return long Either the timeout value specified in the security element in jboss-esb.xml otherwise the value in jbossesb-properties.xml
+ * @throws SecurityServiceException If the value specified in jbossesb-properties.xml cannot be parsed. If the value in jboss-esb.xml cannot be parsed, only a warning will be issued.
+ */
+ long getSecurityContextTimeout(final SecurityConfig securityConfig) throws SecurityServiceException
+ {
+ String timeoutStr = securityConfig.getProperties().get(Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT);
+ if (timeoutStr != null)
+ {
+ try
+ {
+ return Long.parseLong(timeoutStr);
+ }
+ catch (final NumberFormatException ignore)
+ {
+ LOGGER.warn("Could not parse '" + timeoutStr +"' to a long. Please make sure the the value of the property '" + Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT + "' in jbossesb-xml is a valid long(ms)");
+ // fallback to global configuration.
+ }
+ }
+ return SecurityContext.getConfigurationTimeout();
+ }
}
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/PublicCryptoUtil.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/PublicCryptoUtil.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/PublicCryptoUtil.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -44,6 +44,7 @@
import org.jboss.soa.esb.util.ClassUtil;
/**
+ * Util for encrypting/decrypting using assymmetric keys.
*
* @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
*
@@ -71,6 +72,78 @@
}
}
+ public byte[] encrypt(final Serializable object) throws SecurityServiceException
+ {
+ if (!isSecurityConfigured)
+ {
+ return null;
+ }
+
+ ByteArrayInputStream plainInStream;
+ try
+ {
+ plainInStream = new ByteArrayInputStream(getBytes(object));
+ }
+ catch (final IOException e)
+ {
+ throw new SecurityServiceException(e.getMessage(), e);
+ }
+
+ ByteArrayOutputStream encryptedOutStream = new ByteArrayOutputStream();
+
+ try
+ {
+ byte[] buf = new byte[100];
+ int bufLength;
+ while ( (bufLength = plainInStream.read(buf)) != -1)
+ {
+ byte[] tmp = CryptoUtil.encrypt(copyBytes(buf,bufLength), publicKey, transformation);
+ encryptedOutStream.write(tmp);
+ encryptedOutStream.flush();
+ }
+ return encryptedOutStream.toByteArray();
+ }
+ catch (final IOException e)
+ {
+ throw new SecurityServiceException(e.getMessage(), e);
+ }
+ }
+
+ public Serializable decrypt(final byte[] bytes) throws SecurityServiceException
+ {
+ if (!isSecurityConfigured)
+ {
+ return null;
+ }
+ ByteArrayInputStream encryptedBytesInStream = new ByteArrayInputStream(bytes);
+
+ ByteArrayOutputStream decryptedBytesOutStream = new ByteArrayOutputStream();
+
+ byte[] decryptBytes = null;
+ try
+ {
+ byte[] buf = new byte[128];
+ int bufLenth;
+ while ( (bufLenth = encryptedBytesInStream.read(buf)) != -1)
+ {
+ byte[] tmp = CryptoUtil.decrypt( copyBytes(buf,bufLenth),(PrivateKey)key, transformation);
+ decryptedBytesOutStream.write(tmp);
+ decryptedBytesOutStream.flush();
+ decryptBytes = decryptedBytesOutStream.toByteArray();
+ }
+ }
+ catch (final IOException e)
+ {
+ throw new SecurityServiceException(e.getMessage(), e);
+ }
+ finally
+ {
+ try { decryptedBytesOutStream.close(); } catch (IOException ignore) { log.error(ignore.getMessage(),ignore); }
+ }
+
+ return toSerializable(decryptBytes);
+ }
+
private void init() throws SecurityServiceException
{
String keystorePath = Configuration.getSecurityServicePublicKeystore();
@@ -152,78 +225,6 @@
return bout.toByteArray();
}
- public byte[] encrypt(final Serializable object) throws SecurityServiceException
- {
- if (!isSecurityConfigured)
- {
- return null;
- }
-
- ByteArrayInputStream plainInStream;
- try
- {
- plainInStream = new ByteArrayInputStream(getBytes(object));
- }
- catch (final IOException e)
- {
- throw new SecurityServiceException(e.getMessage(), e);
- }
-
- ByteArrayOutputStream encryptedOutStream = new ByteArrayOutputStream();
-
- try
- {
- byte[] buf = new byte[100];
- int bufLength;
- while ( (bufLength = plainInStream.read(buf)) != -1)
- {
- byte[] tmp = CryptoUtil.encrypt(copyBytes(buf,bufLength),publicKey, transformation);
- encryptedOutStream.write(tmp);
- encryptedOutStream.flush();
- }
- return encryptedOutStream.toByteArray();
- }
- catch (final IOException e)
- {
- throw new SecurityServiceException(e.getMessage(), e);
- }
- }
-
- public Serializable decrypt(final byte[] bytes) throws SecurityServiceException
- {
- if (!isSecurityConfigured)
- {
- return null;
- }
- ByteArrayInputStream encryptedBytesInStream = new ByteArrayInputStream(bytes);
-
- ByteArrayOutputStream decryptedBytesOutStream = new ByteArrayOutputStream();
-
- byte[] decryptBytes = null;
- try
- {
- byte[] buf = new byte[128];
- int bufLenth;
- while ( (bufLenth = encryptedBytesInStream.read(buf)) != -1)
- {
- byte[] tmp = CryptoUtil.decrypt( copyBytes(buf,bufLenth),(PrivateKey)key, transformation);
- decryptedBytesOutStream.write(tmp);
- decryptedBytesOutStream.flush();
- decryptBytes = decryptedBytesOutStream.toByteArray();
- }
- }
- catch (final IOException e)
- {
- throw new SecurityServiceException(e.getMessage(), e);
- }
- finally
- {
- try { decryptedBytesOutStream.close(); } catch (IOException ignore) { log.error(ignore.getMessage(),ignore); }
- }
-
- return toSerializable(decryptBytes);
- }
-
private Serializable toSerializable(final byte[] decryptBytes) throws SecurityServiceException
{
ObjectInputStream inputStream = null;
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/SecurityContext.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/SecurityContext.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/SecurityContext.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -22,9 +22,6 @@
import static org.jboss.soa.esb.services.security.principals.Group.ROLES_GROUP_NAME;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.Principal;
import java.security.acl.Group;
@@ -32,20 +29,28 @@
import java.util.Enumeration;
import java.util.Set;
+import javax.crypto.SealedObject;
import javax.security.auth.Subject;
import org.jboss.internal.soa.esb.assertion.AssertArgument;
import org.jboss.internal.soa.esb.services.security.PrivateCryptoUtil;
+import org.jboss.soa.esb.common.Configuration;
+import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.services.security.auth.AuthenticationRequest;
-import org.mvel.ast.AssertNode;
/**
* Security Context contains security related information.
* <p/>
+ *
* Note that even though a Subject object instance is serialiable,
* its private and public credentials are not(they are transient).
+ * <p>
* Also not that the Principal interface is not serializable but
* all implemenations should be.
+ * <p>
+ * When created a SecurityContext will be given a timeout argument which
+ * is the time in milliseconds after which the context is considered
+ * invalid.
*
* @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
* @since 4.4
@@ -55,34 +60,43 @@
{
private static final long serialVersionUID = 1L;
+ private static transient ThreadLocal<SealedObject> securityContextTl = new ThreadLocal<SealedObject>();
+
+ private static long globalConfiguredTimeout;
+
+ /**
+ * The Subject associated with this context.
+ */
private final Subject subject;
- private Set<?> pubCredentials;
+ /**
+ * Timeout (ms) for the security context. Defaults to 5 mins.
+ */
+ private long timeout = 30000;
- private Set<?> privCredentials;
+ /**
+ * Time of creation.
+ */
+ private long timeOfCreation = System.currentTimeMillis();
- public SecurityContext()
+ /**
+ * Creates a SecurityContext associating the passed in Subject with it.
+ *
+ * @param subject The Subject that is to be associated with this security context.
+ * @param timeout A timeout which specifies how long this Security Context is valid for. Must be a positiv value.
+ */
+ public SecurityContext(final Subject subject, final long timeout)
{
- subject = new Subject();
- }
-
- public SecurityContext(Subject subject)
- {
AssertArgument.isNotNull(subject, "subject");
this.subject = subject;
- }
- public Subject getSubject()
- {
- return subject;
+ if ( timeout < -1 )
+ {
+ throw new IllegalArgumentException("'timeout' for SecurityContext must not be negative other then '-1' which indicates a SecurityContext that never expires.");
+ }
+ this.timeout = timeout;
}
- @Override
- public String toString()
- {
- return "SecurityContext [" + subject + "]";
- }
-
public boolean isCallerInRole( final String roleName )
{
Set<Principal> principals = subject.getPrincipals();
@@ -108,35 +122,6 @@
return false;
}
- private void writeObject(final ObjectOutputStream out) throws IOException
- {
- out.defaultWriteObject();
- out.writeObject(subject.getPrivateCredentials());
- out.writeObject(subject.getPublicCredentials());
- }
-
- private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
- {
- in.defaultReadObject();
- privCredentials = (Set<?>) in.readObject();
- pubCredentials = (Set<?>) in.readObject();
- }
-
- final Set<? extends Principal> getPrincipals()
- {
- return Collections.unmodifiableSet(subject.getPrincipals());
- }
-
- final Set<?> getPubCredentials()
- {
- return Collections.unmodifiableSet(pubCredentials);
- }
-
- public Set<?> getPrivCredentials()
- {
- return Collections.unmodifiableSet(privCredentials);
- }
-
/**
* Will check if the passed in {@link AuthenticationRequest} contains the
* same security information (Principal and credentials) as the this context.
@@ -176,38 +161,114 @@
}
}
}
-
return false;
}
- public static SecurityContext decryptContext(final byte[] encrypt) throws SecurityServiceException
+ public long getTimeOfCreation()
{
+ return timeOfCreation;
+ }
+
+ /**
+ * Timeout if milliseconds.
+ *
+ * @return long The timeout (ms) for this security context.
+ */
+ public long getTimeout()
+ {
+ return timeout;
+ }
+
+ public boolean isValid()
+ {
+ if ( timeout == -1 )
+ {
+ return true;
+ }
+
+ return timeOfCreation + timeout > System.currentTimeMillis();
+ }
+
+ public Subject getSubject()
+ {
+ return subject;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "SecurityContext [isValid " + isValid() + ", timeout :" + timeout + ", timeOfCreation : " + timeOfCreation + "]";
+ }
+
+ // package protected methods
+
+ final Set<? extends Principal> getPrincipals()
+ {
+ return Collections.unmodifiableSet(subject.getPrincipals());
+ }
+
+ // static methods
+
+ public static SecurityContext decryptContext(final SealedObject sealedObject) throws SecurityServiceException
+ {
+ if (sealedObject == null)
+ return null;
+
SecurityContext context = null;
- if (encrypt == null)
- return context;
-
- Serializable decrypted = PrivateCryptoUtil.INSTANCE.decrypt(encrypt);
+ Serializable decrypted = PrivateCryptoUtil.INSTANCE.unSealObject(sealedObject);
if (decrypted instanceof SecurityContext)
{
context = (SecurityContext) decrypted;
- final Subject subject = context.getSubject();
- final Set<?> publCreds = context.getPubCredentials();
- if (publCreds != null )
- {
- subject.getPublicCredentials().addAll(publCreds);
- }
- final Set<?> privCreds = context.getPrivCredentials();
- if (privCreds != null)
- {
- subject.getPrivateCredentials().addAll(privCreds);
- }
}
return context;
}
- public static byte[] encryptContext(final SecurityContext context) throws SecurityServiceException
+ public static SealedObject encryptContext(final SecurityContext context) throws SecurityServiceException
{
- return PrivateCryptoUtil.INSTANCE.encrypt(context);
+ return PrivateCryptoUtil.INSTANCE.sealObject(context);
}
+ /**
+ * Get the globally configured security context timeout.
+ * @return
+ * @throws SecurityServiceException
+ */
+ public static long getConfigurationTimeout() throws SecurityServiceException
+ {
+ if (globalConfiguredTimeout == 0l)
+ {
+ globalConfiguredTimeout = getGlobalConfigurationTimeout();
+ }
+ return globalConfiguredTimeout;
+ }
+
+ public static void setSecurityContext(final SealedObject sealedObject)
+ {
+ SecurityContext.securityContextTl.set(sealedObject);
+ }
+
+ public static SealedObject getSecurityContext()
+ {
+ return SecurityContext.securityContextTl.get();
+ }
+
+ private static long getGlobalConfigurationTimeout() throws SecurityServiceException
+ {
+ final String timeoutStr = Configuration.getSecurityServiceContextTimeout();
+ if (timeoutStr == null)
+ {
+ throw new SecurityServiceException("No timeout was configured for the security context. Please set the value of '" + Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT + "' to the timeout you desire");
+ }
+ else
+ {
+ try
+ {
+ return Long.parseLong(timeoutStr.trim());
+ }
+ catch(final NumberFormatException e)
+ {
+ throw new SecurityServiceException("The value of '" + Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT + "' must be specified as a long");
+ }
+ }
+ }
}
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/auth/AuthenticationRequestImpl.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/auth/AuthenticationRequestImpl.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/auth/AuthenticationRequestImpl.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -41,6 +41,8 @@
{
private static final long serialVersionUID = 1L;
+ private static transient ThreadLocal<byte[]> encryptedAuthRequest = new ThreadLocal<byte[]>();
+
private Principal principal;
private Set<?> credentials;
private Map<String,?> properties;
@@ -69,7 +71,17 @@
return principal;
}
- public static class Builder
+ public static byte[] getEncryptedAuthRequest()
+ {
+ return encryptedAuthRequest.get();
+ }
+
+ public static void setEncryptedAuthRequest(byte[] encryptedAuthRequest)
+ {
+ AuthenticationRequestImpl.encryptedAuthRequest.set(encryptedAuthRequest);
+ }
+
+ public static class Builder
{
private Principal principal;
private Set<Object> credentials = new HashSet<Object>();
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/util/CryptoUtil.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/util/CryptoUtil.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/src/org/jboss/soa/esb/services/security/util/CryptoUtil.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -21,6 +21,7 @@
package org.jboss.soa.esb.services.security.util;
import java.security.InvalidKeyException;
+import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
@@ -41,7 +42,7 @@
{
private CryptoUtil() {}
- public static byte[] decrypt(final byte[] bytes, final PrivateKey key, final String transformation) throws SecurityServiceException
+ public static byte[] decrypt(final byte[] bytes, final Key key, final String transformation) throws SecurityServiceException
{
try
{
@@ -71,7 +72,7 @@
}
}
- public static byte[] encrypt(byte[] text, PublicKey key, String transformation) throws SecurityServiceException
+ public static byte[] encrypt(byte[] text, Key key, String transformation) throws SecurityServiceException
{
try
{
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/JaasSecurityServiceUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/JaasSecurityServiceUnitTest.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/JaasSecurityServiceUnitTest.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.net.URL;
import java.security.Principal;
@@ -75,7 +76,7 @@
credentials.add(password);
AuthenticationRequest authRequest = new AuthenticationRequestImpl.Builder(principal, credentials).build();
- SecurityContext context = new SecurityContext(subject);
+ SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
service.configure();
service.authenticate(configInfo, context, authRequest);
@@ -90,7 +91,7 @@
Builder builder = new SecurityConfig.Builder("SuccessfulLogin");
builder.runAs("adminRole");
SecurityConfig configInfo = builder.build();
- SecurityContext context = new SecurityContext(subject);
+ SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
service.authenticate(configInfo, context, null);
Set<Principal> principals = subject.getPrincipals( Principal.class );
assertEquals( 2, principals.size() );
@@ -107,7 +108,7 @@
subject.getPrincipals().add(group);
- SecurityContext context = new SecurityContext(subject);
+ SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
service.authenticate(configInfo, context, null);
Set<Principal> principals = subject.getPrincipals( Principal.class );
@@ -121,7 +122,7 @@
Builder builder = new SecurityConfig.Builder("SuccessfulLogin");
builder.runAs(roleName);
SecurityConfig configInfo = builder.build();
- SecurityContext context = new SecurityContext(subject);
+ SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
service.authenticate(configInfo, context, null);
assertTrue( service.isCallerInRole(subject, new Role(roleName)));
}
@@ -131,7 +132,7 @@
{
Builder builder = new SecurityConfig.Builder("FailureLogin");
SecurityConfig configInfo = builder.build();
- SecurityContext context = new SecurityContext(subject);
+ SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
service.authenticate( configInfo, context, null );
}
@@ -142,12 +143,53 @@
builder.runAs("esbRole");
builder.rolesAllowed("esbRole");
SecurityConfig configInfo = builder.build();
- SecurityContext context = new SecurityContext(subject);
+ SecurityContext context = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
service.authenticate( configInfo, context, null );
boolean checkRolesAllowed = service.checkRolesAllowed(configInfo.getRolesAllowed(), context);
assertTrue(checkRolesAllowed);
}
+ @Test
+ public void refresh() throws SecurityServiceException
+ {
+ Runnable runnable = new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ threadLogin();
+ }
+ catch (final SecurityServiceException ignore)
+ {
+ ignore.printStackTrace();
+ }
+ }
+ };
+ for (int i = 0; i < 1000; i++)
+ {
+ Thread t1 = new Thread(runnable);
+ Thread t2 = new Thread(runnable);
+ t1.start();
+ t2.start();
+ }
+ }
+
+ private void threadLogin() throws SecurityServiceException
+ {
+ Builder builder = new SecurityConfig.Builder("SuccessfulLogin");
+ SecurityConfig configInfo = builder.build();
+ SecurityContext context = new SecurityContext(new Subject(), SecurityContext.getConfigurationTimeout());
+ try
+ {
+ service.authenticate( configInfo, context, null );
+ }
+ catch (SecurityServiceException e)
+ {
+ fail(e.getMessage());
+ }
+ }
+
@Before
public void setup() throws ConfigurationException
{
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtilUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtilUnitTest.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/PrivateCryptoUtilUnitTest.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -20,17 +20,14 @@
*/
package org.jboss.internal.soa.esb.services.security;
-import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.io.Serializable;
import java.net.URL;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.Provider;
-import java.security.Security;
+import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SealedObject;
import junit.framework.JUnit4TestAdapter;
@@ -54,13 +51,14 @@
private String jbossEsbProperties;
@Test
- public void encryptAndDecrypt() throws SecurityServiceException
+ public void sealObject() throws SecurityServiceException, IllegalBlockSizeException, IOException
{
- String object = "some texti: dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
- byte[] encrypted = PrivateCryptoUtil.INSTANCE.encrypt(object);
- assertFalse(object.equals(new String(encrypted)));
+ final String object = getLongString(5000);
- Serializable plainObject = PrivateCryptoUtil.INSTANCE.decrypt(encrypted);
+ final SealedObject sealedObject = PrivateCryptoUtil.INSTANCE.sealObject(object);
+ assertNotNull(sealedObject);
+
+ final Serializable plainObject = PrivateCryptoUtil.INSTANCE.unSealObject(sealedObject);
assertEquals(object, plainObject);
}
@@ -81,6 +79,16 @@
}
}
+ private String getLongString(final int size)
+ {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < size; i++)
+ {
+ sb.append(i);
+ }
+ return sb.toString();
+ }
+
public static junit.framework.Test suite()
{
return new JUnit4TestAdapter(PrivateCryptoUtilUnitTest.class);
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/security-properties.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/security-properties.xml 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/internal/soa/esb/services/security/security-properties.xml 2008-10-20 09:08:16 UTC (rev 23518)
@@ -41,11 +41,11 @@
<property name="org.jboss.soa.esb.services.security.implementationClass" value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>
<property name="org.jboss.soa.esb.services.security.callbackHandler" value="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
- <property name="org.jboss.soa.esb.services.security.privateKeystore" value="privateKeyStore"/>
- <property name="org.jboss.soa.esb.services.security.privateKeystorePassword" value="testKeystorePassword"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyAlias" value="testAlias"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyPassword" value="testPassword"/>
+ <property name="org.jboss.soa.esb.services.security.sealAlgorithm" value="TripleDES"/>
+ <property name="org.jboss.soa.esb.services.security.sealKeySize" value="168"/>
+ <property name="org.jboss.soa.esb.services.security.contextTimeout" value="30000"/>
+
</properties>
<properties name="registry">
<property name="org.jboss.soa.esb.registry.queryManagerURI" value="org.apache.juddi.registry.local.InquiryService#inquire"/>
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipelineUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipelineUnitTest.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/ActionProcessingPipelineUnitTest.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -24,12 +24,15 @@
import java.io.Serializable;
import java.net.URL;
+import java.util.concurrent.TimeUnit;
+import javax.crypto.SealedObject;
import javax.security.auth.Subject;
import junit.framework.TestCase;
import org.jboss.internal.soa.esb.services.registry.MockRegistry;
+import org.jboss.internal.soa.esb.services.security.PrivateCryptoUtil;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.common.Environment;
import org.jboss.soa.esb.common.ModulePropertyManager;
@@ -39,6 +42,8 @@
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.format.MessageFactory;
import org.jboss.soa.esb.services.security.PublicCryptoUtil;
+import org.jboss.soa.esb.services.security.SecurityConfig;
+import org.jboss.soa.esb.services.security.SecurityConfigUtil;
import org.jboss.soa.esb.services.security.SecurityContext;
import org.jboss.soa.esb.services.security.SecurityService;
import org.jboss.soa.esb.services.security.SecurityServiceException;
@@ -69,7 +74,7 @@
jbossEsbProperties = System.getProperty(Environment.PROPERTIES_FILE);
URL resource = ClassUtil.getResource("security-properties.xml", getClass());
System.setProperty(Environment.PROPERTIES_FILE, "abs://" + resource.getFile());
-
+
URL loginConfig = ClassUtil.getResource("test_jaas.config", getClass());
System.setProperty("java.security.auth.login.config", loginConfig.getFile());
}
@@ -461,13 +466,15 @@
Message message = MessageFactory.getInstance().getMessage();
// create an AuthenticationRequest which is needed to authenticate if the security
- AuthenticationRequest build = new AuthenticationRequestImpl.Builder().build();
- message.getContext().setContext(SecurityService.AUTH_REQUEST, PublicCryptoUtil.INSTANCE.encrypt((Serializable) build));
+ AuthenticationRequest authRequest = new AuthenticationRequestImpl.Builder().build();
+ byte[] encryptedAuthRequest = PublicCryptoUtil.INSTANCE.encrypt((Serializable) authRequest);
+ message.getContext().setContext(SecurityService.AUTH_REQUEST, encryptedAuthRequest);
final boolean result = pipeline.process(message);
assertTrue(result);
assertEquals(new TestPrincipal("test").getName(), MockSecuredActionProcessor.getSubject().getPrincipals().iterator().next().getName());
+ assertEquals(encryptedAuthRequest, AuthenticationRequestImpl.getEncryptedAuthRequest());
pipeline.destroy() ;
checkOrder(MockActionInfo.getDestroyList()) ;
}
@@ -528,11 +535,10 @@
// create and encrypt the security context. This simulates a call for a service
// that has already been authentcated..
- SecurityContext securityContext = new SecurityContext(subject);
- byte[] encrypt = SecurityContext.encryptContext(securityContext);
+ SecurityContext securityContext = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
+ SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+ message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
- message.getContext().setContext(SecurityService.CONTEXT, encrypt);
-
final boolean result = pipeline.process(message);
assertTrue(result);
@@ -544,6 +550,89 @@
checkOrder(MockActionInfo.getDestroyList()) ;
}
+ public void testSecuredWithExistingSecurityContextExpired() throws Exception
+ {
+ final ConfigTree configTree = new ConfigTree("parent") ;
+ addSecurityConfig(configTree, "adminRole", null, "SuccessfulLogin", null);
+ configTree.setAttribute(ListenerTagNames.MEP_ATTRIBUTE_TAG, ListenerTagNames.MEP_ONE_WAY) ;
+
+ addAction(configTree, MockSecuredActionProcessor.class.getName(), "process", null, null) ;
+
+ final ActionProcessingPipeline pipeline = new ActionProcessingPipeline(configTree) ;
+ pipeline.initialise() ;
+ checkOrder(MockActionInfo.getInitialiseList()) ;
+
+ Message message = MessageFactory.getInstance().getMessage();
+
+ Subject subject = new Subject();
+ // add principal
+ User user = new User("AustinPowerwich");
+ subject.getPrincipals().add(user);
+ // add public credentials
+ byte[] publicCred = "publicsecret".getBytes();
+ subject.getPublicCredentials().add(publicCred);
+ // add private credentials
+ byte[] privateCred = "privatesecret".getBytes();
+ subject.getPrivateCredentials().add(privateCred);
+
+ // create and encrypt the security context. This simulates a call for a service
+ // that has already been authentcated...but with a very short timeout.
+ SecurityContext securityContext = new SecurityContext(subject, 10);
+
+ TimeUnit.SECONDS.sleep(1);
+
+ SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+ message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
+
+ boolean process = pipeline.process(message);
+ assertFalse(process);
+
+ pipeline.destroy() ;
+ checkOrder(MockActionInfo.getDestroyList()) ;
+ }
+
+ public void testSecuredWithSecurityContextOverriddenTimeout() throws Exception
+ {
+ final long timeout = 90000;
+
+ // setup config tree
+ final ConfigTree configTree = new ConfigTree("parent") ;
+ final ConfigTree securityConfigTree = addSecurityConfig(configTree, "adminRole", null, "SuccessfulLogin", null, timeout);
+ configTree.setAttribute(ListenerTagNames.MEP_ATTRIBUTE_TAG, ListenerTagNames.MEP_ONE_WAY) ;
+ addAction(configTree, MockSecuredActionProcessor.class.getName(), "process", null, null) ;
+
+ final ActionProcessingPipeline pipeline = new ActionProcessingPipeline(configTree) ;
+
+ final SecurityConfig securityConfig = SecurityConfigUtil.createSecurityConfig(securityConfigTree);
+
+ final long contextTimeout = pipeline.getSecurityContextTimeout(securityConfig);
+
+ assertEquals(timeout, contextTimeout);
+
+ pipeline.destroy() ;
+ }
+
+ public void testSecuredWithSecurityContextDefaultTimeout() throws Exception
+ {
+ final long timeout = 30000;
+
+ // setup config tree
+ final ConfigTree configTree = new ConfigTree("parent") ;
+ final ConfigTree securityConfigTree = addSecurityConfig(configTree, "adminRole", null, "SuccessfulLogin", null);
+ configTree.setAttribute(ListenerTagNames.MEP_ATTRIBUTE_TAG, ListenerTagNames.MEP_ONE_WAY) ;
+ addAction(configTree, MockSecuredActionProcessor.class.getName(), "process", null, null) ;
+
+ final ActionProcessingPipeline pipeline = new ActionProcessingPipeline(configTree) ;
+
+ final SecurityConfig securityConfig = SecurityConfigUtil.createSecurityConfig(securityConfigTree);
+
+ final long contextTimeout = pipeline.getSecurityContextTimeout(securityConfig);
+
+ assertEquals(timeout, contextTimeout);
+
+ pipeline.destroy() ;
+ }
+
public void testSecuredWithSecurityContextRolesAllowedNegativeCheck() throws Exception
{
final ConfigTree configTree = new ConfigTree("parent") ;
@@ -565,11 +654,10 @@
subject.getPublicCredentials().add(publicCred);
byte[] privateCred = "privatesecret".getBytes();
subject.getPrivateCredentials().add(privateCred);
- SecurityContext securityContext = new SecurityContext(subject);
- byte[] encrypt = SecurityContext.encryptContext(securityContext);
+ SecurityContext securityContext = new SecurityContext(subject, SecurityContext.getConfigurationTimeout());
+ SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+ message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
- message.getContext().setContext(SecurityService.CONTEXT, encrypt);
-
try
{
pipeline.process(message);
@@ -638,4 +726,22 @@
return securityElement;
}
+ private ConfigTree addSecurityConfig(
+ final ConfigTree parent,
+ final String runAs,
+ final String callerIdentity,
+ final String moduleName,
+ final String rolesAllowed,
+ final long timeout)
+ {
+ ConfigTree securityElement = this.addSecurityConfig(parent, runAs, callerIdentity, moduleName, rolesAllowed);
+ if (timeout != 0l)
+ {
+ ConfigTree property = new ConfigTree("property", securityElement);
+ property.setAttribute("name", Environment.SECURITY_SERVICE_CONTEXT_TIMEOUT);
+ property.setAttribute("value", Long.toString(timeout));
+ }
+ return securityElement;
+ }
+
}
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/security-properties.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/security-properties.xml 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/listeners/message/security-properties.xml 2008-10-20 09:08:16 UTC (rev 23518)
@@ -41,16 +41,17 @@
<property name="org.jboss.soa.esb.services.security.implementationClass" value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>
<property name="org.jboss.soa.esb.services.security.callbackHandler" value="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
- <property name="org.jboss.soa.esb.services.security.privateKeystore" value="privateKeyStore"/>
- <property name="org.jboss.soa.esb.services.security.privateKeystorePassword" value="testKeystorePassword"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyAlias" value="testAlias"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyPassword" value="testPassword"/>
+ <property name="org.jboss.soa.esb.services.security.sealAlgorithm" value="TripleDES"/>
+ <property name="org.jboss.soa.esb.services.security.sealKeySize" value="168"/>
+ <property name="org.jboss.soa.esb.services.security.contextTimeout" value="30000"/>
+
<property name="org.jboss.soa.esb.services.security.publicKeystore" value="publicKeyStore"/>
<property name="org.jboss.soa.esb.services.security.publicKeystorePassword" value="testKeystorePassword"/>
<property name="org.jboss.soa.esb.services.security.publicKeyAlias" value="testAlias"/>
<property name="org.jboss.soa.esb.services.security.publicKeyPassword" value="testPassword"/>
<property name="org.jboss.soa.esb.services.security.publicKeyTransformation" value="RSA/ECB/PKCS1Padding"/>
+
</properties>
<properties name="registry">
<property name="org.jboss.soa.esb.registry.queryManagerURI" value="org.apache.juddi.registry.local.InquiryService#inquire"/>
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/PublicCryptoUtilUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/PublicCryptoUtilUnitTest.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/PublicCryptoUtilUnitTest.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -53,7 +53,7 @@
@Test
public void encryptAndDecrypt() throws SecurityServiceException, InvalidKeyException, NoSuchAlgorithmException, IOException, ClassNotFoundException
{
- String object = "some textaalddddddddddddddaldkfjlakjfafadlalkfdalfjkfladsjfalkfjfljsafkjalkfjjafjlkafjfjjfaadlasajfkafkjalalfkjakljdljfajfjajfljalkfjlafljalsjfjj";
+ final String object = getLongString(5000);
byte[] encrypted = PublicCryptoUtil.INSTANCE.encrypt(object);
assertFalse(object.equals(new String(encrypted)));
@@ -71,6 +71,16 @@
}
}
+ private String getLongString(final int size)
+ {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < size; i++)
+ {
+ sb.append(i);
+ }
+ return sb.toString();
+ }
+
@Before
public void setup() throws ConfigurationException
{
@@ -79,6 +89,8 @@
System.setProperty(Environment.PROPERTIES_FILE, "abs://" + resource.getFile());
}
+
+
@After
public void tearDown()
{
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/SecurityContextUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/SecurityContextUnitTest.java 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/SecurityContextUnitTest.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -20,8 +20,8 @@
*/
package org.jboss.soa.esb.services.security;
-import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -32,7 +32,9 @@
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.HashSet;
+import java.util.concurrent.TimeUnit;
+import javax.crypto.SealedObject;
import javax.security.auth.Subject;
import junit.framework.JUnit4TestAdapter;
@@ -53,7 +55,8 @@
import org.junit.Test;
/**
- *
+ * Unit test for SecurityContext.
+ * <p/>
* @author <a href="mailto:dbevenius at redhat.com">Daniel Bevenius</a>
*
*/
@@ -70,7 +73,7 @@
roles.addMember( new Role("Admin"));
subject.getPrincipals().add(roles);
- SecurityContext securityContext = new SecurityContext(subject);
+ SecurityContext securityContext = new SecurityContext(subject, 30000);
boolean callerInRole = securityContext.isCallerInRole("Admin");
assertTrue( callerInRole );
}
@@ -84,7 +87,7 @@
byte[] publicCred = "secret".getBytes();
subject.getPublicCredentials().add(publicCred);
- SecurityContext securityContext = new SecurityContext(subject);
+ SecurityContext securityContext = new SecurityContext(subject, 30000l);
assertEquals( user, securityContext.getSubject().getPrincipals().iterator().next() );
assertEquals( publicCred, securityContext.getSubject().getPublicCredentials().iterator().next());
@@ -102,7 +105,6 @@
assertTrue (readObject instanceof SecurityContext);
SecurityContext deserialized = (SecurityContext)readObject;
assertEquals( user, deserialized.getSubject().getPrincipals().iterator().next() );
- assertEquals( new String(publicCred), new String((byte[])deserialized.getPubCredentials().iterator().next()));
}
@Test
@@ -114,12 +116,11 @@
byte[] publicCred = "secret".getBytes();
subject.getPublicCredentials().add(publicCred);
- SecurityContext securityContext = new SecurityContext(subject);
+ SecurityContext securityContext = new SecurityContext(subject, 30000l);
Message message = MessageFactory.getInstance().getMessage(MessageType.JAVA_SERIALIZED);
- byte[] encryptContext = SecurityContext.encryptContext(securityContext);
- message.getContext().setContext(SecurityService.CONTEXT, encryptContext);
+ SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+ message.getContext().setContext(SecurityService.CONTEXT, sealedObject);
-
// serialize object
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bout);
@@ -133,10 +134,8 @@
// assert that the content is still matches.
assertTrue (readObject instanceof Message);
Message deserializedMsg = (Message) readObject;
- SecurityContext deserialized = SecurityContext.decryptContext((byte[]) deserializedMsg.getContext().getContext(SecurityService.CONTEXT));
+ SecurityContext deserialized = SecurityContext.decryptContext((SealedObject) deserializedMsg.getContext().getContext(SecurityService.CONTEXT));
assertEquals( user, deserialized.getSubject().getPrincipals().iterator().next() );
- //assertEquals( new String(publicCred), new String((byte[])deserialized.getPubCredentials().iterator().next()));
- assertEquals( new String(publicCred), new String((byte[])deserialized.getSubject().getPublicCredentials().iterator().next()));
}
@Test
@@ -150,13 +149,12 @@
byte[] privateCred = "privatesecret".getBytes();
subject.getPrivateCredentials().add(privateCred);
- SecurityContext securityContext = new SecurityContext(subject);
- byte[] encrypt = SecurityContext.encryptContext(securityContext);
- assertNotNull(encrypt);
+ SecurityContext securityContext = new SecurityContext(subject, 30000);
+ SealedObject sealedObject = SecurityContext.encryptContext(securityContext);
+ assertNotNull(sealedObject);
- SecurityContext decryptContext = SecurityContext.decryptContext(encrypt);
- assertEquals( new String(publicCred), new String((byte[])decryptContext.getPubCredentials().iterator().next()));
- assertEquals( new String(privateCred), new String((byte[])decryptContext.getPrivCredentials().iterator().next()));
+ SecurityContext decryptContext = SecurityContext.decryptContext(sealedObject);
+ assertEquals( user, decryptContext.getSubject().getPrincipals().iterator().next());
}
@Test
@@ -170,7 +168,7 @@
byte[] privateCred = "privatesecret".getBytes();
subject.getPrivateCredentials().add(privateCred);
- SecurityContext securityContext = new SecurityContext(subject);
+ SecurityContext securityContext = new SecurityContext(subject, 30000);
HashSet<Object> credentials = new HashSet<Object>();
credentials.add(publicCred);
@@ -186,6 +184,41 @@
assertFalse(securityContext.compareTo(null));
}
+ @Test
+ public void timeout() throws InterruptedException
+ {
+ final Subject subject = new Subject();
+ SecurityContext context = new SecurityContext(subject, 30000);
+ assertTrue("Default is 5 min so context should be valid", context.isValid());
+
+ context = new SecurityContext(subject, 100);
+ TimeUnit.SECONDS.sleep(1);
+ assertFalse(context.isValid());
+
+ context = new SecurityContext(subject, 1000);
+ assertTrue(context.isValid());
+ }
+
+ @Test
+ public void constructWithNeverExpiringContext()
+ {
+ SecurityContext securityContext = new SecurityContext(new Subject(), -1);
+ assertTrue(securityContext.isValid());
+ }
+
+ @Test (expected = IllegalArgumentException.class )
+ public void shouldThrowIfTimeoutIsNegative()
+ {
+ new SecurityContext(new Subject(), -2);
+ }
+
+ @Test
+ public void getConfigurationTimeout() throws SecurityServiceException
+ {
+ final long timeout = SecurityContext.getConfigurationTimeout();
+ assertEquals("timeout should match the value in security-properties.xml", 30000l, timeout);
+ }
+
@Before
public void setup() throws ConfigurationException
{
Modified: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/security-properties.xml
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/security-properties.xml 2008-10-20 08:22:02 UTC (rev 23517)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/security-properties.xml 2008-10-20 09:08:16 UTC (rev 23518)
@@ -41,16 +41,17 @@
<property name="org.jboss.soa.esb.services.security.implementationClass" value="org.jboss.internal.soa.esb.services.security.JaasSecurityService"/>
<property name="org.jboss.soa.esb.services.security.callbackHandler" value="org.jboss.internal.soa.esb.services.security.UserPassCallbackHandler"/>
- <property name="org.jboss.soa.esb.services.security.privateKeystore" value="privateKeyStore"/>
- <property name="org.jboss.soa.esb.services.security.privateKeystorePassword" value="testKeystorePassword"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyAlias" value="testAlias"/>
- <property name="org.jboss.soa.esb.services.security.privateKeyPassword" value="testPassword"/>
+ <property name="org.jboss.soa.esb.services.security.sealAlgorithm" value="TripleDES"/>
+ <property name="org.jboss.soa.esb.services.security.sealKeySize" value="168"/>
+ <property name="org.jboss.soa.esb.services.security.contextTimeout" value="30000"/>
+
<property name="org.jboss.soa.esb.services.security.publicKeystore" value="publicKeyStore"/>
<property name="org.jboss.soa.esb.services.security.publicKeystorePassword" value="testKeystorePassword"/>
<property name="org.jboss.soa.esb.services.security.publicKeyAlias" value="testAlias"/>
<property name="org.jboss.soa.esb.services.security.publicKeyPassword" value="testPassword"/>
<property name="org.jboss.soa.esb.services.security.publicKeyTransformation" value="RSA/ECB/PKCS1Padding"/>
+
</properties>
<properties name="registry">
<property name="org.jboss.soa.esb.registry.queryManagerURI" value="org.apache.juddi.registry.local.InquiryService#inquire"/>
Added: labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/CryptoUtilUnitTest.java
===================================================================
--- labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/CryptoUtilUnitTest.java (rev 0)
+++ labs/jbossesb/branches/JBESB_4_4_GA_CP/product/rosetta/tests/src/org/jboss/soa/esb/services/security/util/CryptoUtilUnitTest.java 2008-10-20 09:08:16 UTC (rev 23518)
@@ -0,0 +1,122 @@
+/*
+ * JBoss, Home of Professional Open Source Copyright 2008, Red Hat Middleware
+ * LLC, and individual contributors by the @authors tag. See the copyright.txt
+ * 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.jboss.soa.esb.services.security.util;
+
+import static org.junit.Assert.*;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import org.jboss.soa.esb.services.security.SecurityServiceException;
+import org.junit.Test;
+
+import junit.framework.JUnit4TestAdapter;
+
+/**
+ * Unit test from CryptoUtil.
+ *
+ * @author <a href="mailto:dbevenius at jboss.com">Daniel Bevenius</a>
+ *
+ */
+public class CryptoUtilUnitTest
+{
+ @Test
+ public void encryptDecryptRSA() throws NoSuchAlgorithmException, SecurityServiceException
+ {
+ final String payload = "Some text...";
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+ keyGen.initialize(1024);
+ KeyPair keyPair = keyGen.generateKeyPair();
+
+ byte[] encrypt = CryptoUtil.encrypt(payload.getBytes() , keyPair.getPublic(), keyPair.getPublic().getAlgorithm());
+ byte[] decrypt = CryptoUtil.decrypt(encrypt, keyPair.getPrivate(), keyPair.getPrivate().getAlgorithm());
+ assertEquals(payload, new String(decrypt));
+ }
+
+ @Test
+ public void encryptDecryptDES() throws NoSuchAlgorithmException, SecurityServiceException
+ {
+ final String payload = "Some text...";
+ KeyGenerator keyGen = KeyGenerator.getInstance("DES");
+ keyGen.init(56);
+ SecretKey secretKey = keyGen.generateKey();
+ final String transformation = "DES/ECB/PKCS5Padding";
+
+ byte[] encrypt = CryptoUtil.encrypt(payload.getBytes() , secretKey, transformation);
+
+ byte[] decrypt = CryptoUtil.decrypt(encrypt, secretKey, transformation);
+ assertEquals(payload, new String(decrypt));
+ }
+
+ @Test
+ public void encryptDecryptTripleDES() throws NoSuchAlgorithmException, SecurityServiceException
+ {
+ dumpSecurityProviders();
+ final String payload = "Some text...";
+ KeyGenerator keyGen = KeyGenerator.getInstance("Blowfish");
+ keyGen.init(128);
+ SecretKey secretKey = keyGen.generateKey();
+ final String transformation = "Blowfish/ECB/PKCS5Padding";
+
+ byte[] encrypt = CryptoUtil.encrypt(payload.getBytes() , secretKey, transformation);
+
+ byte[] decrypt = CryptoUtil.decrypt(encrypt, secretKey, transformation);
+ assertEquals(payload, new String(decrypt));
+ }
+
+ @Test
+ public void encryptDecryptTripleEAS() throws NoSuchAlgorithmException, SecurityServiceException
+ {
+ final String payload = "Some text...";
+ KeyGenerator keyGen = KeyGenerator.getInstance("AES");
+ keyGen.init(128);
+ SecretKey secretKey = keyGen.generateKey();
+ final String transformation = "AES/ECB/PKCS5Padding";
+
+ byte[] encrypt = CryptoUtil.encrypt(payload.getBytes() , secretKey, transformation);
+
+ byte[] decrypt = CryptoUtil.decrypt(encrypt, secretKey, transformation);
+ assertEquals(payload, new String(decrypt));
+ }
+
+
+ @SuppressWarnings("unused")
+ private void dumpSecurityProviders()
+ {
+ Provider[] providers = Security.getProviders();
+ for (Provider provider : providers)
+ {
+ System.out.println(provider.getServices());
+ }
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new JUnit4TestAdapter(CryptoUtilUnitTest.class);
+ }
+
+}
More information about the jboss-svn-commits
mailing list