All Downloads are FREE. Search and download functionalities are using the official Maven repository.

br.com.esec.icpm.signer.security.SecurityConfig Maven / Gradle / Ivy

package br.com.esec.icpm.signer.security;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import br.com.esec.icpm.signer.ws.rest.PemUtils;
import br.com.esec.icpm.util.FileUtils;
import br.com.esec.icpm.util.ReadableFileUtils;
import br.com.esec.icpm.util.StreamUtils;
import br.com.esec.icpm.util.UrlUtils;

public class SecurityConfig {
	
	protected static Log log = LogFactory.getLog(SecurityConfig.class);

	private static final String provider = "SUN";

	private static final String CERTILLION_KEYSTORE = "certillion.keystore";
	private static final String CERTILLION_STORETYPE = "certillion.storetype";
	private static final String CERTILLION_STOREPASS = "certillion.storepass";
	private static final String CERTILLION_ALIAS = "certillion.alias";
	private static final String CERTILLION_TRUSTSTORE = "certillion.truststore";
	private static final String CERTILLION_TRUSTSTORETYPE = "certillion.truststoretype";
	private static final String CERTILLION_TRUSTSTOREPASS = "certillion.truststorepass";
	private static final String CERTILLION_ALLOWALLHOSTS = "certillion.allowallhosts";

	private static final String DEFAUL_ALLOW_HOSTS = "false";
	private static final String DEFAULT_TRUSTSTORE_TYPE = "DIR";
	private static final String DEFAULT_KEYSTORE_TYPE = "JKS";

	private static String keystoreUrlPath = System.getProperty(CERTILLION_KEYSTORE, getenv(CERTILLION_KEYSTORE));
	private static String keystoreType = System.getProperty(CERTILLION_STORETYPE, getenv(CERTILLION_STORETYPE, DEFAULT_KEYSTORE_TYPE));
	private static String keystorePassword = System.getProperty(CERTILLION_STOREPASS, getenv(CERTILLION_STOREPASS, ""));
	private static String keyAlias = System.getProperty(CERTILLION_ALIAS, getenv(CERTILLION_ALIAS));
	private static String truststorePath = System.getProperty(CERTILLION_TRUSTSTORE, getenv(CERTILLION_TRUSTSTORE));
	private static String truststoreType = System.getProperty(CERTILLION_TRUSTSTORETYPE, getenv(CERTILLION_TRUSTSTORETYPE, DEFAULT_TRUSTSTORE_TYPE));
	private static String truststorePassword = System.getProperty(CERTILLION_TRUSTSTOREPASS, getenv(CERTILLION_TRUSTSTOREPASS));
	private static boolean allowAllHosts = Boolean.valueOf(System.getProperty(CERTILLION_ALLOWALLHOSTS, getenv(CERTILLION_ALLOWALLHOSTS, DEFAUL_ALLOW_HOSTS)));

	private static boolean validated = false;

	public static Properties getConfig() {
		if (!validated)
			validate();

		Properties properties = new Properties();
		
		String keystoreUrlPathEnsured = ReadableFileUtils.ensure(keystoreUrlPath);
		if (!StringUtils.isEmpty(keystoreUrlPathEnsured)) {
			properties.put("org.apache.ws.security.crypto.provider", CryptoProvider.class.getCanonicalName());
			properties.put("org.apache.ws.security.crypto.merlin.keystore.file", keystoreUrlPathEnsured); // Merlin need a file path to load with FileInputStream
			properties.put("org.apache.ws.security.crypto.merlin.keystore.type", keystoreType);
			properties.put("org.apache.ws.security.crypto.merlin.keystore.password", keystorePassword);
			properties.put("org.apache.ws.security.crypto.merlin.keystore.alias", keyAlias);

			// TODO: Revisar pq isso existe e se ainda há a necessidade de existir
			properties.put("org.apache.ws.security.crypto.merlin.cert.provider", provider);
			// properties.put("org.apache.ws.security.crypto.merlin.keystore.provider", "SunJSSE");
		}
		
		return properties;
	}

	private static KeyStore keystore;
	public static KeyStore getKeystore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
		if (keystore == null) {
			if (!validated)
				validate();

			keystore = buildKeyStore();
		}

		return keystore;
	}

	private static KeyStore truststore;
	public static KeyStore getTruststore() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
		if (truststore == null) {
			if (!validated)
				validate();
			
			truststore = buildTruststore();
		}
			
		return truststore;
	}

	public static void validate() {
		try {
			log.info("Security config is using '" + keystoreUrlPath + "' as key store.");
			
			KeyStore keyStore = buildKeyStore();
			if (keyStore != null) {

				if (keyAlias == null) {
					Enumeration aliases = keyStore.aliases();
					while (aliases.hasMoreElements()) {
						String alias = (String) aliases.nextElement();
						if (keyStore.isKeyEntry(alias))
							keyAlias = alias;
					}
				}

				Key key = keyStore.getKey(keyAlias, keystorePassword.toCharArray());
				if (key == null) {
					throw new IllegalStateException("The key store is invalid or password is wrong!");
				}
				key = null;
			}

			KeyStore trustStore = buildTruststore();

			validated = true;
		} catch (UnrecoverableKeyException e) {
			throw new IllegalStateException("The key store is invalid or password is wrong!", e);
		} catch (KeyStoreException e) {
			throw new IllegalStateException("The key store is invalid or password is wrong!", e);
		} catch (NoSuchAlgorithmException e) {
			throw new IllegalStateException("The key store is invalid or password is wrong!", e);
		} catch (CertificateException e) {
			throw new IllegalStateException("The key store is invalid or password is wrong!", e);
		} catch (IOException e) {
			throw new IllegalStateException("The key store is invalid or password is wrong!", e);
		}
	}

	private static KeyStore buildKeyStore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
		if (StringUtils.isEmpty(keystoreUrlPath))
			return null;
		KeyStore keyStore = KeyStore.getInstance(keystoreType);
		keyStore.load(StreamUtils.load(keystoreUrlPath), keystorePassword.toCharArray());
		return keyStore;
	}
	
	private static KeyStore buildTruststore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
		KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
		trustStore.load(null);

		final List certificates = loadCertificates();
		if (certificates == null || certificates.isEmpty())
			return null;

		for (X509Certificate certificate : certificates) {
			final String alias = certificate.getSubjectX500Principal().getName();
			trustStore.setCertificateEntry(alias, certificate);
		}
		return trustStore;
	}

	private static List loadCertificates() throws CertificateException, KeyStoreException {
		if (StringUtils.isEmpty(truststorePath)) {
			return null;
		}

		List certificates = null;

		if (DEFAULT_TRUSTSTORE_TYPE.equals(truststoreType)) {
			certificates = loadAsDirectory();
		} else {
			certificates = loadAsFile();
		}

		return certificates;
	}

	private static List loadAsFile() {
		try {
			KeyStore keystore = KeyStore.getInstance(truststoreType);
			keystore.load(StreamUtils.load(truststorePath), truststorePassword.toCharArray());

			List certificates = new ArrayList();

			Enumeration aliases = keystore.aliases();
			while (aliases.hasMoreElements()) {
				String alias = aliases.nextElement();

				Certificate certificate = keystore.getCertificate(alias);

				if (certificate != null) {
					certificates.add((X509Certificate) certificate);
				}
			}
			
			if (certificates == null || certificates.isEmpty()) {
				throw new IllegalArgumentException(
						"Could not load the trusted-certificate. The path '" + truststorePath + "' is not a valid " + truststoreType + " truststore.");			
			}
			
			log.trace("The security-helper found " + certificates.size() + " trusted certificates in " + truststorePath + "'.");

			return certificates;
		} catch (IOException e) {
			throw new IllegalArgumentException("Could not load the trusted-certificate", e);
		} catch (KeyStoreException e) {
			throw new IllegalArgumentException("Could not load the trusted-certificate", e);
		} catch (NoSuchAlgorithmException e) {
			throw new IllegalArgumentException("Could not load the trusted-certificate", e);
		} catch (CertificateException e) {
			throw new IllegalArgumentException("Could not load the trusted-certificate", e);
		}
	}

	private static List loadAsDirectory() {
		try {
			File truststoreDir = FileUtils.getFile(truststorePath);

			if (!truststoreDir.isDirectory()) {
				throw new IllegalStateException("The truststore need to be a directory.");
			}

			List certificates = new ArrayList();

			for (File file : truststoreDir.listFiles()) {
				if (!file.isFile()) {
					throw new IllegalStateException("Inside the truststore directory need to be only certificates.");
				}

				InputStream inputStream = null;
				try {
					if (PemUtils.isPem(file)) {
						inputStream = PemUtils.convertPemToDer(file);
					} else {
						inputStream = new FileInputStream(file);
					}

					CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
					X509Certificate certificate = (X509Certificate) certificateFactory.generateCertificate(inputStream);
					certificates.add(certificate);
				} finally {
					IOUtils.closeQuietly(inputStream);
				}
			}
			
			if (certificates == null || certificates.isEmpty()) {
				throw new IllegalArgumentException(
						"Could not load the trusted-certificate. The path '" + truststorePath + "' is not a valid " + truststoreType + " truststore.");			
			}
			
			log.trace("The security-helper found " + certificates.size() + " trusted certificates in " + truststorePath + "'.");

			return certificates;
		} catch (CertificateException e) {
			throw new IllegalArgumentException("Could not load the trusted-certificate", e);
		} catch (IOException e) {
			throw new IllegalArgumentException("Could not load the trusted-certificate", e);
		}
	}

	public static void load(String propertiesFilename) throws IOException {
		load(propertiesFilename, SecurityConfig.class);
	}

	public static void load(String propertiesFilename, @Deprecated Class clazzToLoadResource) throws IOException {
		InputStream inStream = StreamUtils.load(propertiesFilename);

		Properties properties = new Properties();
		properties.load(inStream);

		setKeystorePath(properties.getProperty("keystorePath"));
		setKeystoreType(properties.getProperty("keystoreType"));
		setKeystorePassword(properties.getProperty("keystorePassword"));
		setKeyAlias(properties.getProperty("keyAlias"));
		setTruststorePath(properties.getProperty("truststorePath"));
		setTruststoreType(properties.getProperty("truststoreType"));
		setTruststorePassword(properties.getProperty("truststorePassword"));
		setAllowAllHosts(Boolean.parseBoolean(properties.getProperty("allowAllHosts")));
	}

	@Deprecated
	public static void set(String keystorePath, String keystoreType, String keystorePassword, String keyAlias, String truststorePath, String truststoreType,
			String truststorePassword, Boolean allowAllHosts) {
		setKeystorePath(keystorePath);
		setKeystoreType(keystoreType);
		setKeystorePassword(keystorePassword);
		setKeyAlias(keyAlias);
		setTruststorePath(truststorePath);
		setTruststoreType(truststoreType);
		setTruststorePassword(truststorePassword);
		setAllowAllHosts(allowAllHosts);
	}

	public static String getKeyAlias() {
		return keyAlias;
	}

	public static String getKeystorePath() {
		return keystoreUrlPath;
	}

	public static String getKeystoreType() {
		return keystoreType;
	}

	public static String getKeystorePassword() {
		return keystorePassword;
	}

	public static String getTruststorePath() {
		return truststorePath;
	}

	public static boolean isAllowAllHosts() {
		return allowAllHosts;
	}

	public static void setAllowAllHosts(Boolean allowAllHosts) {
		if (allowAllHosts != null)
			SecurityConfig.allowAllHosts = allowAllHosts;
	}

	public static void setTruststorePassword(String truststorePassword) {
		if (!StringUtils.isEmpty(truststorePassword))
			SecurityConfig.truststorePassword = truststorePassword;
	}

	public static void setTruststoreType(String truststoreType) {
		if (!StringUtils.isEmpty(truststoreType))
			SecurityConfig.truststoreType = truststoreType;
	}

	public static void setTruststorePath(String truststorePath) {
		if (!StringUtils.isEmpty(truststorePath))
			SecurityConfig.truststorePath = extractAbsolutePath(truststorePath);
	}

	public static void setKeyAlias(String keyAlias) {
		if (!StringUtils.isEmpty(keyAlias))
			SecurityConfig.keyAlias = keyAlias;
	}

	public static void setKeystorePassword(String keystorePassword) {
		if (!StringUtils.isEmpty(keystorePassword))
			SecurityConfig.keystorePassword = keystorePassword;
	}

	public static void setKeystoreType(String keystoreType) {
		if (!StringUtils.isEmpty(keystoreType))
			SecurityConfig.keystoreType = keystoreType;
	}

	public static void setKeystorePath(String keystorePath) {
		if (!StringUtils.isEmpty(keystorePath))
			SecurityConfig.keystoreUrlPath = extractAbsolutePath(keystorePath);
	}

	private static String extractAbsolutePath(String path) {
		return UrlUtils.getAbsoluteUrl(path).toString();
	}

	private static String getenv(String name) {
		return getenv(name, null);
	}

	private static String getenv(String name, String def) {
		final String value = System.getenv(name);
		return StringUtils.isEmpty(value) ? def : value;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy