package org.cagrid.trust.tools; import org.apache.commons.lang.StringUtils; import org.cagrid.core.commandline.BaseCommandLine; import org.cagrid.core.xml.XMLUtils; import org.cagrid.gaards.pki.CertUtil; import org.cagrid.trust.model.*; import java.io.File; import java.io.FileOutputStream; import java.math.BigInteger; import java.security.KeyStore; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Properties; /** * Created by langella on 3/25/14. */ public class Bootstrapper extends BaseCommandLine { private static final String PROPERTIES_FILE = "src/main/resources/bootstrapper.properties"; private static final String TRUST_SERVICE_DIR = "cagrid-trust"; private static final String CERTIFICATES_DIR = "certificates"; private static final String SYNC_DESCRIPTION_FILE = "sync-description.xml"; private static final String TRUST_SERVICE_CFG = "cagrid.trust.service.cfg"; private static final String TRUSTED_CA_PROMPT = "Please enter the location of a trust root certificate authority"; private static final String TRUSTED_CA_PROPERTY = "cagrid.trust.ca.certificate."; private static final String TRUSTSTORE_FILE_NAME = "truststore.jks"; private static final String TRUSTSTORE_LOCATION_PROPERTY_VALUE = "${karaf.base}/etc/" + TRUST_SERVICE_DIR + "/" + TRUSTSTORE_FILE_NAME; private static final String TRUSTSTORE_LOCATION_PROPERTY = "cagrid.trust.service.truststore.file"; private static final String TRUSTSTORE_PASSWORD_PROMPT = "Please enter a password for the truststore"; private static final String TRUSTSTORE_PASSWORD_PROPERTY = "cagrid.trust.service.truststore.password"; private static final String GTS_URL_PROMPT = "Please enter the URL of the GTS you want the trust service to sync with"; private static final String GTS_URL_PROPERTY = "cagrid.trust.service.gts.url"; private static final String GTS_IDENTITY_PROMPT = "Please enter the identity of the GTS you want the trust service to sync with"; private static final String GTS_IDENTITY_PROPERTY = "cagrid.trust.service.gts.identity"; private static final String GTS_EXPIRATION_HOURS_PROMPT = "Please enter the number of hours a certificate authority should be trusted for without getting an update from the GTS"; private static final String GTS_EXPIRATION_HOURS_PROPERTY = "cagrid.trust.service.gts.expiration.hours"; private static final String GTS_EXPIRATION_MINUTES_PROMPT = "Please enter the number of minutes a certificate authority should be trusted for without getting an update from the GTS"; private static final String GTS_EXPIRATION_MINUTES_PROPERTY = "cagrid.trust.service.gts.expiration.minutes"; private static final String GTS_EXPIRATION_SECONDS_PROMPT = "Please enter the number of seconds a certificate authority should be trusted for without getting an update from the GTS"; private static final String GTS_EXPIRATION_SECONDS_PROPERTY = "cagrid.trust.service.gts.expiration.seconds"; private static final String GTS_NEXT_SYNC_PROMPT = "Please enter how often (milliseconds) the trust service should syn with the GTS"; private static final String GTS_NEXT_SYNC_PROPERTY = "cagrid.trust.service.sync.repeat.interval"; private static final String CONFIGURER_PROMPT = "Please specifiy a client configurer to use (truststoreClientConfigurer OR trustServiceClientConfigurer)"; private static final String CONFIGURER_PROPERTY = "cagrid.trust.service.client.configurer"; private List<X509Certificate> certificates; private File trustEtcDir; private Properties serviceProperties; public Bootstrapper(File propertiesFile) throws Exception { super(propertiesFile); } public Bootstrapper(Properties properties) throws Exception { super(properties); } public static void main(String[] args) { try { Bootstrapper main = new Bootstrapper(new File(PROPERTIES_FILE)); main.execute(); } catch (Exception e) { e.printStackTrace(); } } @Override public void execute() throws Exception { System.out.println("*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*"); System.out.println("* Trust Service Bootstrapper *"); System.out.println("*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*"); System.out.println(""); serviceProperties = new Properties(); trustEtcDir = new File(getServiceMixEtc().getAbsolutePath() + File.separator + TRUST_SERVICE_DIR); trustEtcDir.mkdirs(); buildTrustList(); createAndConfigureTruststore(); writeTrustedCertificates(); writeSyncDescription(); String nextSync = getValue(GTS_NEXT_SYNC_PROMPT, GTS_NEXT_SYNC_PROPERTY); serviceProperties.setProperty(GTS_NEXT_SYNC_PROPERTY, nextSync); configureConfigurer(); File config = new File(getServiceMixEtc(), TRUST_SERVICE_CFG); serviceProperties.store(new FileOutputStream(config), "Trust Service Configuration saved by bootstrapper on " + new Date()); } private void configureConfigurer() { String configurer = getValue(CONFIGURER_PROMPT, CONFIGURER_PROPERTY); serviceProperties.setProperty(CONFIGURER_PROPERTY, configurer); } private void writeSyncDescription() { String gtsURL = getValue(GTS_URL_PROMPT, GTS_URL_PROPERTY); String gtsIdentity = getValue(GTS_IDENTITY_PROMPT, GTS_IDENTITY_PROPERTY); SyncDescription des = new SyncDescription(); SyncDescriptor descriptor = new SyncDescriptor(); des.getSyncDescriptors().add(descriptor); descriptor.setGTS(gtsURL); if (StringUtils.isBlank(gtsIdentity)) { descriptor.setPerformAuthorization(false); } else { descriptor.setPerformAuthorization(true); descriptor.setGTSIdentity(gtsIdentity); } Integer hours = Integer.valueOf(getValue(GTS_EXPIRATION_HOURS_PROMPT, GTS_EXPIRATION_HOURS_PROPERTY)); Integer minutes = Integer.valueOf(getValue(GTS_EXPIRATION_MINUTES_PROMPT, GTS_EXPIRATION_MINUTES_PROPERTY)); Integer seconds = Integer.valueOf(getValue(GTS_EXPIRATION_SECONDS_PROMPT, GTS_EXPIRATION_SECONDS_PROPERTY)); Expiration expiration = new Expiration(); expiration.setHours(hours); expiration.setMinutes(minutes); expiration.setSeconds(seconds); descriptor.setExpiration(expiration); TrustedAuthorityFilter f = new TrustedAuthorityFilter(); f.setStatus(Status.TRUSTED); f.setLifetime(Lifetime.VALID); descriptor.getTrustedAuthorityFilters().add(f); ExcludedCAs excluded = new ExcludedCAs(); for (X509Certificate cert : this.certificates) { excluded.getCASubjects().add(cert.getSubjectDN().getName()); } des.setExcludedCAs(excluded); des.setDeleteInvalidFiles(false); des.setNextSync(BigInteger.valueOf(600)); DateFilter df = new DateFilter(); df.setMonth(1); df.setYear(0); df.setDay(0); des.setCacheSize(df); File syncDescription = new File(this.trustEtcDir.getAbsolutePath() + File.separator + SYNC_DESCRIPTION_FILE); try { XMLUtils.toXMLFile(des, syncDescription); System.out.println("Successfully wrote the sync description to " + syncDescription.getAbsolutePath() + "."); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } private void writeTrustedCertificates() { try { File dir = new File(this.trustEtcDir.getAbsolutePath() + File.separator + CERTIFICATES_DIR); dir.mkdirs(); int count = 0; for (X509Certificate cert : this.certificates) { File caFile = new File(dir.getAbsolutePath() + File.separator + "trust-ca-" + count + ".cert"); CertUtil.writeCertificate(cert, caFile); System.out.println("Successfully wrote the CA " + cert.getSubjectDN().getName() + " to " + caFile.getAbsolutePath() + "."); count = count + 1; } } catch (Exception e) { e.printStackTrace(); System.exit(1); } } private void createAndConfigureTruststore() { try { File f = new File(this.trustEtcDir.getAbsolutePath() + File.separator + TRUSTSTORE_FILE_NAME); KeyStore keyStore = KeyStore.getInstance("jks"); keyStore.load(null); int count = 0; for (X509Certificate cert : this.certificates) { String alias = "trustca" + count; keyStore.setEntry(alias, new KeyStore.TrustedCertificateEntry(cert), null); count = count + 1; System.out.println("Added the CA " + cert.getSubjectDN().getName() + " to the truststore under the alias " + alias + "."); } String password = getValue(TRUSTSTORE_PASSWORD_PROMPT, TRUSTSTORE_PASSWORD_PROPERTY); FileOutputStream fos = new FileOutputStream(f); keyStore.store(fos, password.toCharArray()); fos.close(); serviceProperties.setProperty(TRUSTSTORE_LOCATION_PROPERTY, TRUSTSTORE_LOCATION_PROPERTY_VALUE); serviceProperties.setProperty(TRUSTSTORE_PASSWORD_PROPERTY, password); System.out.println("Truststore created at " + f.getAbsolutePath()); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } private void buildTrustList() { certificates = new ArrayList<X509Certificate>(); int count = 0; boolean requestAnother = true; String property = TRUSTED_CA_PROPERTY + count; while (requestAnother) { String certLocation = getValue(TRUSTED_CA_PROMPT, property); try { X509Certificate cert = CertUtil.loadCertificate(new File(certLocation)); System.out.println("Successfully loaded the certificate " + cert.getSubjectDN().getName() + " from the file " + certLocation + "."); this.certificates.add(cert); count = count + 1; property = TRUSTED_CA_PROPERTY + count; if (getProperties().getProperty(property) == null) { requestAnother = getBooleanValue("Would you like to add another trust root certificate authority (true|false)?", "foo"); } } catch (Exception e) { e.printStackTrace(); } } } }