You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by co...@apache.org on 2013/08/21 20:54:26 UTC

svn commit: r1516255 - in /cxf/branches/2.7.x-fixes/services/xkms/xkms-client: ./ src/main/java/org/apache/cxf/xkms/cache/ src/main/java/org/apache/cxf/xkms/crypto/ src/test/ src/test/java/ src/test/java/org/ src/test/java/org/apache/ src/test/java/org...

Author: coheigea
Date: Wed Aug 21 18:54:26 2013
New Revision: 1516255

URL: http://svn.apache.org/r1516255
Log:
Adding XKMS validate caching + some caching unit tests


Conflicts:
	services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/crypto/XkmsCryptoProvider.java

Added:
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/cxf/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/cxf/xkms/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/cxf/xkms/cache/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/cxf/xkms/cache/XKMSClientCacheTest.java
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/alice.jks
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/bob.jks
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/cxfca.jks
Modified:
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/pom.xml
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/EHCacheXKMSClientCache.java
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/XKMSClientCache.java
    cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/crypto/XkmsCryptoProvider.java

Modified: cxf/branches/2.7.x-fixes/services/xkms/xkms-client/pom.xml
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-client/pom.xml?rev=1516255&r1=1516254&r2=1516255&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-client/pom.xml (original)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-client/pom.xml Wed Aug 21 18:54:26 2013
@@ -32,7 +32,7 @@
         <version>2.7.7-SNAPSHOT</version>
         <relativePath>../../../parent/pom.xml</relativePath>
     </parent>
-
+    
     <dependencies>
         <dependency>
             <groupId>org.apache.cxf.services.xkms</groupId>
@@ -73,9 +73,29 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
+        <testSourceDirectory>${basedir}/src/test/java</testSourceDirectory>
+        <testResources>
+            <testResource>
+                <directory>src/test/java</directory>
+                <excludes>
+                    <exclude>**/*.java</exclude>
+                </excludes>
+            </testResource>
+            <testResource>
+                <directory>src/test/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </testResource>
+        </testResources>
         <plugins>
             <plugin>
                 <groupId>org.apache.felix</groupId>

Modified: cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/EHCacheXKMSClientCache.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/EHCacheXKMSClientCache.java?rev=1516255&r1=1516254&r2=1516255&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/EHCacheXKMSClientCache.java (original)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/EHCacheXKMSClientCache.java Wed Aug 21 18:54:26 2013
@@ -20,7 +20,6 @@
 package org.apache.cxf.xkms.cache;
 
 import java.io.File;
-import java.io.IOException;
 import java.net.URL;
 
 import net.sf.ehcache.Cache;
@@ -34,38 +33,45 @@ import net.sf.ehcache.config.DiskStoreCo
 
 import org.apache.cxf.Bus;
 import org.apache.cxf.BusFactory;
+import org.apache.cxf.buslifecycle.BusLifeCycleListener;
+import org.apache.cxf.buslifecycle.BusLifeCycleManager;
 import org.apache.cxf.common.classloader.ClassLoaderUtils;
 
 /**
  * An in-memory EHCache implementation of the XKMSClientCache interface. 
  */
-public class EHCacheXKMSClientCache implements XKMSClientCache {
+public class EHCacheXKMSClientCache implements XKMSClientCache, BusLifeCycleListener {
     
     public static final String CACHE_KEY = "cxf.xkms.client.cache";
     private static final String DEFAULT_CONFIG_URL = "cxf-xkms-client-ehcache.xml";
     
     private Ehcache cache;
     private CacheManager cacheManager;
+    private Bus bus;
     
     public EHCacheXKMSClientCache() {
         this(DEFAULT_CONFIG_URL, null);
     }
     
-    public EHCacheXKMSClientCache(Bus bus) {
-        this(DEFAULT_CONFIG_URL, bus);
+    public EHCacheXKMSClientCache(Bus cxfBus) {
+        this(DEFAULT_CONFIG_URL, cxfBus);
     }
     
     public EHCacheXKMSClientCache(String configFileURL) {
         this(configFileURL, null);
     }
     
-    public EHCacheXKMSClientCache(String configFileURL, Bus bus) {
-        createCache(configFileURL, bus);
+    public EHCacheXKMSClientCache(String configFileURL, Bus cxfBus) {
+        createCache(configFileURL, cxfBus);
+        this.bus = cxfBus;
+        if (bus != null) {
+            bus.getExtension(BusLifeCycleManager.class).registerLifeCycleListener(this);
+        }
     }
     
-    private void createCache(String configFile, Bus bus) {
-        if (bus == null) {
-            bus = BusFactory.getThreadDefaultBus(true);
+    private void createCache(String configFile, Bus cxfBus) {
+        if (cxfBus == null) {
+            cxfBus = BusFactory.getThreadDefaultBus(true);
         }
         URL configFileURL = null;
         try {
@@ -79,12 +85,12 @@ public class EHCacheXKMSClientCache impl
         } else {
             Configuration conf = ConfigurationFactory.parseConfiguration(configFileURL);
             
-            if (bus != null) {
-                conf.setName(bus.getId());
+            if (cxfBus != null) {
+                conf.setName(cxfBus.getId());
                 DiskStoreConfiguration dsc = conf.getDiskStoreConfiguration();
                 if (dsc != null && "java.io.tmpdir".equals(dsc.getOriginalPath())) {
                     String path = conf.getDiskStoreConfiguration().getPath() + File.separator
-                        + bus.getId();
+                        + cxfBus.getId();
                     conf.getDiskStoreConfiguration().setPath(path);
                 }
             }
@@ -117,7 +123,7 @@ public class EHCacheXKMSClientCache impl
         return null;
     }
     
-    public void close() throws IOException {
+    public void close() {
         if (cacheManager != null) {
             if (cache != null) {
                 cache.removeAll();
@@ -125,7 +131,22 @@ public class EHCacheXKMSClientCache impl
             cacheManager.shutdown();
             cacheManager = null;
             cache = null;
+            
+            if (bus != null) {
+                bus.getExtension(BusLifeCycleManager.class).unregisterLifeCycleListener(this);
+            }
         }
     }
     
+    public void initComplete() {
+    }
+
+    public void preShutdown() {
+        close();
+    }
+
+    public void postShutdown() {
+        close();
+    }
+    
 }

Modified: cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/XKMSClientCache.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/XKMSClientCache.java?rev=1516255&r1=1516254&r2=1516255&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/XKMSClientCache.java (original)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/cache/XKMSClientCache.java Wed Aug 21 18:54:26 2013
@@ -20,7 +20,6 @@
 package org.apache.cxf.xkms.cache;
 
 import java.io.Closeable;
-import java.io.IOException;
 
 public interface XKMSClientCache extends Closeable {
 
@@ -35,5 +34,5 @@ public interface XKMSClientCache extends
      */
     XKMSCacheToken get(String key);
     
-    void close() throws IOException;
+    void close();
 }
\ No newline at end of file

Modified: cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/crypto/XkmsCryptoProvider.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/crypto/XkmsCryptoProvider.java?rev=1516255&r1=1516254&r2=1516255&view=diff
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/crypto/XkmsCryptoProvider.java (original)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/main/java/org/apache/cxf/xkms/crypto/XkmsCryptoProvider.java Wed Aug 21 18:54:26 2013
@@ -112,7 +112,36 @@ public class XkmsCryptoProvider extends 
         if (certs != null) {
             LOG.fine(String.format("Verifying certificate id: %s", certs[0].getSubjectDN()));
         }
-        return certs != null && xkmsInvoker.validateCertificate(certs[0]);
+        
+        XKMSCacheToken cachedToken = null;
+        // Try local cache first
+        if (certs != null && certs.length > 0 && xkmsClientCache != null) {
+            String key = certs[0].getSubjectX500Principal().getName();
+            // Try by Subject DN and IssuerSerial
+            cachedToken = xkmsClientCache.get(key);
+            if (cachedToken == null) {
+                key = getKeyForIssuerSerial(certs[0].getIssuerX500Principal().getName(),
+                                            certs[0].getSerialNumber());
+                cachedToken = xkmsClientCache.get(key);
+            }
+            if (cachedToken != null && cachedToken.isXkmsValidated()) {
+                LOG.fine("Certificate has already been validated by the XKMS service");
+                return true;
+            }
+        }
+        if (certs == null || certs[0] == null || !xkmsInvoker.validateCertificate(certs[0])) {
+            return false;
+        }
+        
+        // Validate Cached token
+        if (cachedToken != null) {
+            cachedToken.setXkmsValidated(true);
+        }
+        
+        // Otherwise, Store in the cache as a validated certificate
+        storeCertificateInCache(certs[0], null, true);
+
+        return true;
     }
 
     @Override
@@ -146,12 +175,8 @@ public class XkmsCryptoProvider extends 
                 .getIssuer(), cryptoType.getSerial());
             
             // Store in the cache
-            if (certificate != null && xkmsClientCache != null) {
-                XKMSCacheToken cacheToken = new XKMSCacheToken(certificate);
-                xkmsClientCache.put(key, cacheToken);
-                // Store it using the Subject DN as well
-                xkmsClientCache.put(certificate.getSubjectX500Principal().getName(), cacheToken);
-            }
+            storeCertificateInCache(certificate, key, false);
+
             return new X509Certificate[] {
                 certificate
             };
@@ -193,14 +218,7 @@ public class XkmsCryptoProvider extends 
         X509Certificate cert = xkmsInvoker.getCertificateForId(application, id);
         
         // Store in the cache
-        if (cert != null && xkmsClientCache != null) {
-            XKMSCacheToken cacheToken = new XKMSCacheToken(cert);
-            xkmsClientCache.put(id.toLowerCase(), cacheToken);
-            // Store it using IssuerSerial as well
-            String key = getKeyForIssuerSerial(cert.getIssuerX500Principal().getName(), 
-                                               cert.getSerialNumber());
-            xkmsClientCache.put(key, cacheToken);
-        }
+        storeCertificateInCache(cert, id.toLowerCase(), false);
 
         return new X509Certificate[] {
             cert
@@ -218,8 +236,8 @@ public class XkmsCryptoProvider extends 
         try {
             localCerts = defaultCrypto.getX509Certificates(cryptoType);
         } catch (Exception e) {
-            LOG.info("Certificate is not found in local keystore and will be requested from XKMS: "
-                     + cryptoType.getAlias());
+            LOG.info("Certificate is not found in local keystore and will be requested from "
+                + "XKMS (first trying the cache): " + cryptoType.getAlias());
         }
         return localCerts;
     }
@@ -237,5 +255,29 @@ public class XkmsCryptoProvider extends 
     private String getKeyForIssuerSerial(String issuer, BigInteger serial) {
         return issuer + "-" + serial.toString(16);
     }
+    
+    private void storeCertificateInCache(X509Certificate certificate, String key, boolean validated) {
+        // Store in the cache
+        if (certificate != null && xkmsClientCache != null) {
+            XKMSCacheToken cacheToken = new XKMSCacheToken(certificate);
+            cacheToken.setXkmsValidated(validated);
+            // Store using a custom key (if any)
+            if (key != null) {
+                xkmsClientCache.put(key, cacheToken);
+            }
+            // Store it using IssuerSerial as well
+            String issuerSerialKey = 
+                getKeyForIssuerSerial(certificate.getIssuerX500Principal().getName(), 
+                                      certificate.getSerialNumber());
+            if (!issuerSerialKey.equals(key)) {
+                xkmsClientCache.put(issuerSerialKey, cacheToken);
+            }
+            // Store it using the Subject DN as well
+            String subjectDNKey = certificate.getSubjectX500Principal().getName();
+            if (!subjectDNKey.equals(key)) {
+                xkmsClientCache.put(subjectDNKey, cacheToken);
+            }
+        }
+    }
 
 }

Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/cxf/xkms/cache/XKMSClientCacheTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/cxf/xkms/cache/XKMSClientCacheTest.java?rev=1516255&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/cxf/xkms/cache/XKMSClientCacheTest.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/java/org/apache/cxf/xkms/cache/XKMSClientCacheTest.java Wed Aug 21 18:54:26 2013
@@ -0,0 +1,113 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.xkms.cache;
+
+import java.math.BigInteger;
+import java.security.KeyStore;
+import java.security.cert.X509Certificate;
+
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+
+/**
+ * A test for the XKMSClientCache
+ */
+public class XKMSClientCacheTest extends org.junit.Assert {
+    
+    private final XKMSClientCache cache;
+    private final X509Certificate alice;
+    private final X509Certificate bob;
+
+    public XKMSClientCacheTest() throws Exception {
+        cache = new EHCacheXKMSClientCache();
+        
+        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+        keystore.load(ClassLoaderUtils.getResourceAsStream("certs/alice.jks", 
+                                                           XKMSClientCacheTest.class), 
+                                                           "password".toCharArray());
+        alice = (X509Certificate)keystore.getCertificate("alice");
+        
+        keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+        keystore.load(ClassLoaderUtils.getResourceAsStream("certs/bob.jks", 
+                                                           XKMSClientCacheTest.class), 
+                                                           "password".toCharArray());
+        bob = (X509Certificate)keystore.getCertificate("bob");
+    }
+    
+    @org.junit.Test
+    public void testCache() {
+        assertNotNull(alice);
+        assertNotNull(bob);
+        
+        XKMSCacheToken aliceToken = new XKMSCacheToken();
+        aliceToken.setX509Certificate(alice);
+        
+        // Put
+        storeCertificateInCache(alice, false);
+        storeCertificateInCache(bob, false);
+        
+        // Get
+        XKMSCacheToken cachedToken = cache.get(alice.getSubjectX500Principal().getName());
+        assertEquals(alice, cachedToken.getX509Certificate());
+        assertFalse(cachedToken.isXkmsValidated());
+        
+        cache.get(getKeyForIssuerSerial(alice.getIssuerX500Principal().getName(), 
+                                        alice.getSerialNumber()));
+        assertEquals(alice, cachedToken.getX509Certificate());
+        assertFalse(cachedToken.isXkmsValidated());
+        
+        cachedToken = cache.get(bob.getSubjectX500Principal().getName());
+        assertEquals(bob, cachedToken.getX509Certificate());
+        assertFalse(cachedToken.isXkmsValidated());
+        
+        cache.get(getKeyForIssuerSerial(bob.getIssuerX500Principal().getName(), 
+                                        bob.getSerialNumber()));
+        assertEquals(bob, cachedToken.getX509Certificate());
+        assertFalse(cachedToken.isXkmsValidated());
+        
+        // Validate
+        cachedToken = cache.get(alice.getSubjectX500Principal().getName());
+        cachedToken.setXkmsValidated(true);
+        
+        cachedToken = cache.get(alice.getSubjectX500Principal().getName());
+        assertTrue(cachedToken.isXkmsValidated());
+        cache.get(getKeyForIssuerSerial(alice.getIssuerX500Principal().getName(), 
+                                        alice.getSerialNumber()));
+        assertTrue(cachedToken.isXkmsValidated());
+    }
+    
+    private void storeCertificateInCache(X509Certificate certificate, boolean validated) {
+        XKMSCacheToken cacheToken = new XKMSCacheToken(certificate);
+        cacheToken.setXkmsValidated(validated);
+        
+        // Store it using IssuerSerial
+        String issuerSerialKey = 
+            getKeyForIssuerSerial(certificate.getIssuerX500Principal().getName(), 
+                                  certificate.getSerialNumber());
+        cache.put(issuerSerialKey, cacheToken);
+
+            // Store it using the Subject DN as well
+        String subjectDNKey = certificate.getSubjectX500Principal().getName();
+        cache.put(subjectDNKey, cacheToken);
+    }
+    
+    private String getKeyForIssuerSerial(String issuer, BigInteger serial) {
+        return issuer + "-" + serial.toString(16);
+    }
+}
\ No newline at end of file

Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/alice.jks
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/alice.jks?rev=1516255&view=auto
==============================================================================
Files cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/alice.jks (added) and cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/alice.jks Wed Aug 21 18:54:26 2013 differ

Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/bob.jks
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/bob.jks?rev=1516255&view=auto
==============================================================================
Files cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/bob.jks (added) and cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/bob.jks Wed Aug 21 18:54:26 2013 differ

Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/cxfca.jks
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/cxfca.jks?rev=1516255&view=auto
==============================================================================
Files cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/cxfca.jks (added) and cxf/branches/2.7.x-fixes/services/xkms/xkms-client/src/test/resources/certs/cxfca.jks Wed Aug 21 18:54:26 2013 differ