Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SPDX-License-Identifier: Apache-2.0

<groupId>org.italiangrid</groupId>
<artifactId>voms-api-java</artifactId>
<version>3.3.6</version>
<version>3.3.7-SNAPSHOT</version>
<packaging>jar</packaging>

<name>voms-api-java</name>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,50 +35,47 @@

/**
*
* The default implementation for the VOMS trust store. This implementation
* <b>does not</b> refresh the trust information on a periodic basis. For an
* updating trust store see {@link DefaultUpdatingVOMSTrustStore}.
* The default implementation for the VOMS trust store. This implementation <b>does not</b> refresh
* the trust information on a periodic basis. For an updating trust store see
* {@link DefaultUpdatingVOMSTrustStore}.
*
* @author Andrea Ceccanti
*
*/
public class DefaultVOMSTrustStore implements VOMSTrustStore {

/**
* The default directory where local VOMS trust information is rooted:
* {@value #DEFAULT_VOMS_DIR}
* The default directory where local VOMS trust information is rooted: {@value #DEFAULT_VOMS_DIR}
**/
public static final String DEFAULT_VOMS_DIR = "/etc/grid-security/vomsdir";

/**
* The filename suffix used to match certificates in the VOMS local trust
* directories
* The filename suffix used to match certificates in the VOMS local trust directories
**/
public static final String CERTIFICATE_FILENAME_SUFFIX = ".pem";

/**
* The filename suffix used to match LSC files in the VOMS local trust
* directories
* The filename suffix used to match LSC files in the VOMS local trust directories
**/
public static final String LSC_FILENAME_SUFFIX = ".lsc";

/**
* The list of local trusted directories that is searched for trust
* information (certs or LSC files)
* The list of local trusted directories that is searched for trust information (certs or LSC
* files)
**/
private final List<String> localTrustedDirs;
protected final List<String> localTrustedDirs;

/** Map of local parsed AA certificates keyed by certificate subject hash **/
private Map<String, X509Certificate> localAACertificatesByHash = new HashMap<String, X509Certificate>();
protected Map<String, X509Certificate> localAACertificatesByHash =
new HashMap<String, X509Certificate>();

/** The set of local parsed LSC information keyed by VO **/
private Map<String, Set<LSCInfo>> localLSCInfo = new HashMap<String, Set<LSCInfo>>();
protected Map<String, Set<LSCInfo>> localLSCInfo = new HashMap<String, Set<LSCInfo>>();

/**
* The trust store status listener that will be notified of changes in this
* trust store
* The trust store status listener that will be notified of changes in this trust store
**/
private VOMSTrustStoreStatusListener listener;
protected VOMSTrustStoreStatusListener listener;

/** The read/write lock that implements thread safety for this store **/
protected final ReadWriteLock rwLock = new ReentrantReadWriteLock();
Expand All @@ -92,14 +89,14 @@ public class DefaultVOMSTrustStore implements VOMSTrustStore {
/** A lock to guard the setting of the status listener **/
protected final Object listenerLock = new Object();

protected final List<String> voName;

/**
* Builds a list of trusted directories containing only
* {@link #DEFAULT_VOMS_DIR}.
* Builds a list of trusted directories containing only {@link #DEFAULT_VOMS_DIR}.
*
* @return a list of default trusted directory containing the
* {@link #DEFAULT_VOMS_DIR}
* @return a list of default trusted directory containing the {@link #DEFAULT_VOMS_DIR}
**/
protected static List<String> buildDefaultTrustedDirs() {
public static List<String> buildDefaultTrustedDirs() {

List<String> tDirs = new ArrayList<String>();
tDirs.add(DEFAULT_VOMS_DIR);
Expand All @@ -108,24 +105,26 @@ protected static List<String> buildDefaultTrustedDirs() {

/**
*
* @param localTrustDirs
* a non-null list of local trust directories
* @param listener
* the {@link VOMSTrustStoreStatusListener} to use for this trust
* store
* @throws IllegalArgumentException
* when the list passed as argument is null
* @param localTrustDirs a non-null list of local trust directories
* @param listener the {@link VOMSTrustStoreStatusListener} to use for this trust store
* @throws IllegalArgumentException when the list passed as argument is null
*
*/
public DefaultVOMSTrustStore(List<String> localTrustDirs,
VOMSTrustStoreStatusListener listener) {
public DefaultVOMSTrustStore(List<String> localTrustDirs, VOMSTrustStoreStatusListener listener) {

this(localTrustDirs, null, listener);
}

public DefaultVOMSTrustStore(List<String> localTrustDirs, List<String> voName,
VOMSTrustStoreStatusListener listener) {

if (localTrustDirs == null)
throw new IllegalArgumentException(
"Please provide a non-null list of local trust directories!");
"Please provide a non-null list of local trust directories!");

this.localTrustedDirs = localTrustDirs;
this.listener = listener;
this.voName = voName;
loadTrustInformation();
}

Expand All @@ -142,8 +141,7 @@ public DefaultVOMSTrustStore(List<String> localTrustDirs) {
/**
* Default constructor.
*
* Sets the local trusted directories to the default of
* {@value #DEFAULT_VOMS_DIR}.
* Sets the local trusted directories to the default of {@value #DEFAULT_VOMS_DIR}.
*
*
*/
Expand All @@ -167,8 +165,8 @@ public List<X509Certificate> getLocalAACertificates() {
read.lock();

try {
return Collections.unmodifiableList(new ArrayList<X509Certificate>(
localAACertificatesByHash.values()));
return Collections
.unmodifiableList(new ArrayList<X509Certificate>(localAACertificatesByHash.values()));
} finally {
read.unlock();
}
Expand Down Expand Up @@ -200,9 +198,8 @@ public LSCInfo getLSC(String voName, String hostname) {
}

/**
* Loads all the certificates in the local directory. Only files with the
* extension matching the {@link #CERTIFICATE_FILENAME_PATTERN} are
* considered.
* Loads all the certificates in the local directory. Only files with the extension matching the
* {@link #CERTIFICATE_FILENAME_PATTERN} are considered.
*
* @param directory
*/
Expand All @@ -228,8 +225,8 @@ public boolean accept(File dir, String name) {
}

/**
* Loads a VOMS AA certificate from a given file and stores this certificate
* in the local map of trusted VOMS AA certificate.
* Loads a VOMS AA certificate from a given file and stores this certificate in the local map of
* trusted VOMS AA certificate.
*
* @param file
*/
Expand All @@ -239,8 +236,8 @@ private void loadCertificateFromFile(File file) {

try {

X509Certificate aaCert = CertificateUtils.loadCertificate(
new FileInputStream(file), Encoding.PEM);
X509Certificate aaCert =
CertificateUtils.loadCertificate(new FileInputStream(file), Encoding.PEM);

// Get certificate subject hash, using the CANL implementation for CA
// files
Expand All @@ -254,9 +251,9 @@ private void loadCertificateFromFile(File file) {
}

} catch (IOException e) {
String errorMessage = String.format(
"Error parsing VOMS trusted certificate from %s. Reason: %s",
file.getAbsolutePath(), e.getMessage());
String errorMessage =
String.format("Error parsing VOMS trusted certificate from %s. Reason: %s",
file.getAbsolutePath(), e.getMessage());
throw new VOMSError(errorMessage, e);
}

Expand All @@ -266,7 +263,7 @@ private void loadCertificateFromFile(File file) {
*
* @param directory
*/
private void loadLSCFromDirectory(File directory) {
protected void loadLSCFromDirectory(File directory) {

directorySanityChecks(directory);

Expand Down Expand Up @@ -299,8 +296,7 @@ public boolean accept(File dir, String name) {
// In the VOMS trust anchor structure, LSC files are named as
// <hostname>.lsc where hostname
// is the name of host where the VOMS AA is running
String hostname = lscFileName.substring(0,
lscFileName.indexOf(LSC_FILENAME_SUFFIX));
String hostname = lscFileName.substring(0, lscFileName.indexOf(LSC_FILENAME_SUFFIX));

LSCInfo info = null;

Expand All @@ -322,46 +318,43 @@ public boolean accept(File dir, String name) {
}

/**
* Performs basic sanity checks performed on a file supposed to hold a VOMS AA
* certificate.
* Performs basic sanity checks performed on a file supposed to hold a VOMS AA certificate.
*
* @param certFile
*/
private void certificateFileSanityChecks(File certFile) {

if (!certFile.exists())
throw new VOMSError("Local VOMS trusted certificate does not exist:"
+ certFile.getAbsolutePath());
throw new VOMSError(
"Local VOMS trusted certificate does not exist:" + certFile.getAbsolutePath());

if (!certFile.canRead())
throw new VOMSError("Local VOMS trusted certificate is not readable:"
+ certFile.getAbsolutePath());
throw new VOMSError(
"Local VOMS trusted certificate is not readable:" + certFile.getAbsolutePath());

}

/**
* Performs basic sanity checks on a directory that is supposed to contain
* VOMS AA certificates and LSC files.
* Performs basic sanity checks on a directory that is supposed to contain VOMS AA certificates
* and LSC files.
*
* @param directory
*/
private void directorySanityChecks(File directory) {
protected void directorySanityChecks(File directory) {

if (!directory.exists())
throw new VOMSError("Local trust directory does not exists:"
+ directory.getAbsolutePath());
throw new VOMSError("Local trust directory does not exists:" + directory.getAbsolutePath());

if (!directory.isDirectory())
throw new VOMSError("Local trust directory is not a directory:"
+ directory.getAbsolutePath());
throw new VOMSError(
"Local trust directory is not a directory:" + directory.getAbsolutePath());

if (!directory.canRead())
throw new VOMSError("Local trust directory is not readable:"
+ directory.getAbsolutePath());
throw new VOMSError("Local trust directory is not readable:" + directory.getAbsolutePath());

if (!directory.canExecute())
throw new VOMSError("Local trust directory is not traversable:"
+ directory.getAbsolutePath());
throw new VOMSError(
"Local trust directory is not traversable:" + directory.getAbsolutePath());

}

Expand All @@ -380,7 +373,7 @@ public void loadTrustInformation() {

if (localTrustedDirs.isEmpty()) {
throw new VOMSError(
"No local trust directory was specified for this trust store. Please provide at least one path where LSC and VOMS service certificates will be searched for.");
"No local trust directory was specified for this trust store. Please provide at least one path where LSC and VOMS service certificates will be searched for.");
}

cleanupStores();
Expand All @@ -404,6 +397,10 @@ public boolean accept(File pathname) {
});

for (File voDir : voDirs) {

if (voName != null && !voName.contains(voDir.getName()))
continue;

loadLSCFromDirectory(voDir);
loadCertificatesFromDirectory(voDir);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
package org.italiangrid.voms.test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.FileInputStream;
Expand All @@ -20,6 +22,7 @@

import org.italiangrid.voms.VOMSError;
import org.italiangrid.voms.store.impl.DefaultVOMSTrustStore;
import org.italiangrid.voms.util.NullListener;
import org.junit.Test;

import eu.emi.security.authn.x509.impl.CertificateUtils;
Expand All @@ -34,17 +37,16 @@ public class TestDefaultVOMSTrustStore {
@Test(expected = VOMSError.class)
public void testEmptyTrustDirsFailure() {

@SuppressWarnings({ "unused", "unchecked" })
DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(
Collections.EMPTY_LIST);
@SuppressWarnings({"unused", "unchecked"})
DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(Collections.EMPTY_LIST);

}

@Test(expected = VOMSError.class)
public void testNonExistentTrustDirsFailure() {

List<String> trustDirs = Arrays.asList(new String[] { "/etc/do/not/exist",
"/etc/grid-security/vomsdir" });
List<String> trustDirs =
Arrays.asList(new String[] {"/etc/do/not/exist", "/etc/grid-security/vomsdir"});

@SuppressWarnings("unused")
DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(trustDirs);
Expand Down Expand Up @@ -75,22 +77,48 @@ public void testEmptyTrustDir() {
}

@Test
public void testCertificateParsing() throws FileNotFoundException,
IOException {
public void testCertificateParsing() throws FileNotFoundException, IOException {

String vomsDir = "src/test/resources/vomsdir";
String certFileName = "src/test/resources/vomsdir/test-host.cnaf.infn.it.pem";
X509Certificate cert = CertificateUtils.loadCertificate(
new FileInputStream(certFileName), Encoding.PEM);
X509Certificate cert =
CertificateUtils.loadCertificate(new FileInputStream(certFileName), Encoding.PEM);

List<String> trustDirs = Arrays.asList(new String[] { vomsDir });
List<String> trustDirs = Arrays.asList(new String[] {vomsDir});

DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(trustDirs);

assertEquals(1, store.getLocalAACertificates().size());

assertTrue(cert.getSubjectX500Principal().equals(
store.getLocalAACertificates().get(0).getSubjectX500Principal()));
assertTrue(cert.getSubjectX500Principal()
.equals(store.getLocalAACertificates().get(0).getSubjectX500Principal()));
}

@Test
public void testAllLSCInStore() {

List<String> trustDirs = Arrays.asList("src/test/resources/vomsdir");

DefaultVOMSTrustStore store = new DefaultVOMSTrustStore(trustDirs, NullListener.INSTANCE);

assertNotNull(store.getLSC("test.vo", "test-host.cnaf.infn.it"));
assertNotNull(store.getLSC("test.vo", "test-multichain.cnaf.infn.it"));
assertNotNull(store.getLSC("test.vo.1", "wilco.cnaf.infn.it"));

}

@Test
public void testLSCForVoInStore() {

List<String> trustDirs = Arrays.asList("src/test/resources/vomsdir");

DefaultVOMSTrustStore store =
new DefaultVOMSTrustStore(trustDirs, Arrays.asList("test.vo"), NullListener.INSTANCE);

assertNotNull(store.getLSC("test.vo", "test-host.cnaf.infn.it"));
assertNotNull(store.getLSC("test.vo", "test-multichain.cnaf.infn.it"));
assertNull(store.getLSC("test.vo.1", "wilco.cnaf.infn.it"));

}

public void testUpdatingVOMSTrustStore() {
Expand Down