/* * Copyright (C) 2014 Intel Corporation * All rights reserved. */ package com.intel.mtwilson.trustagent.setup; import com.intel.dcsg.cpg.crypto.SimpleKeystore; import com.intel.dcsg.cpg.io.FileResource; import com.intel.dcsg.cpg.crypto.Sha1Digest; import com.intel.dcsg.cpg.tls.policy.TlsUtil; import com.intel.dcsg.cpg.tls.policy.impl.AnyProtocolSelector; import com.intel.mtwilson.setup.AbstractSetupTask; import com.intel.mtwilson.trustagent.TrustagentConfiguration; import java.io.File; import java.net.URL; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableEntryException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; /** * Prerequisites: Trust Agent Keystore must already be created * * @author jbuhacoff */ public class DownloadMtWilsonTlsCertificate extends AbstractSetupTask { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DownloadMtWilsonTlsCertificate.class); private TrustagentConfiguration trustagentConfiguration; private String url; private String username; private String password; private File keystoreFile; private String keystorePassword; private SimpleKeystore keystore; private List<String> approved; @Override protected void configure() throws Exception { trustagentConfiguration = new TrustagentConfiguration(getConfiguration()); url = trustagentConfiguration.getMtWilsonApiUrl(); if( url == null || url.isEmpty() ) { configuration("Mt Wilson URL is not set: mtwilson.api.url"); } username = trustagentConfiguration.getMtWilsonApiUsername(); password = trustagentConfiguration.getMtWilsonApiPassword(); if( username == null || username.isEmpty() ) { configuration("Mt Wilson username is not set: mtwilson.api.username"); } if( password == null || password.isEmpty() ) { configuration("Mt Wilson password is not set: mtwilson.api.password"); } keystoreFile = trustagentConfiguration.getTrustagentKeystoreFile(); if( keystoreFile == null || !keystoreFile.exists() ) { configuration("Trust Agent keystore does not exist"); } keystorePassword = trustagentConfiguration.getTrustagentKeystorePassword(); if( keystorePassword == null || keystorePassword.isEmpty() ) { configuration("Trust Agent keystore password is not set"); } approved = trustagentConfiguration.getMtWilsonTlsCertificateFingerprints(); if( approved.isEmpty() ) { configuration("One or more approved TLS certificate fingerprints must be set in MTWILSON_TLS_CERT_SHA1; comma-separated values ok"); } keystore = new SimpleKeystore(new FileResource(keystoreFile), keystorePassword); } @Override protected void validate() throws Exception { try { X509Certificate[] certificates = keystore.getTrustedCertificates(SimpleKeystore.SSL); if( certificates.length == 0 ) { validation("Keystore does not contain any Mt Wilson TLS certificates"); } else { // check to see if any pre-approved certificates are NOT already in our keystore // that's not necessarily an error condition (the approved certs list may be for multiple servers) // but it's an indicator that we should execute this task to ensure that we have the most // current certs ArrayList<String> present = new ArrayList<>(); for(X509Certificate certificate : certificates) { String fingerprint = Sha1Digest.digestOf(certificate.getEncoded()).toHexString(); present.add(fingerprint); } if( !containsAny(present, approved) ) { validation("Keystore does not contain any approved TLS certificates"); } } } catch(NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException | CertificateEncodingException e) { validation("Cannot load certificates from keystore"); } } private boolean containsAny(List<String> list, List<String> any) { for(String item : any) { if( list.contains(item) ) { return true; } } return false; } @Override protected void execute() throws Exception { X509Certificate[] certificates = TlsUtil.getServerCertificates(new URL(url), new AnyProtocolSelector()); ArrayList<X509Certificate> rejected = new ArrayList<>(); ArrayList<X509Certificate> accepted = new ArrayList<>(); for(X509Certificate certificate : certificates) { String fingerprint = Sha1Digest.digestOf(certificate.getEncoded()).toHexString(); if( approved.contains(fingerprint)) { log.debug("Server certificate {} is approved", fingerprint); keystore.addTrustedSslCertificate(certificate, fingerprint); accepted.add(certificate); } else { log.debug("Server certificate {} is rejected", fingerprint); rejected.add(certificate); } } if( !accepted.isEmpty() ) { keystore.save(); } if( accepted.isEmpty() && !rejected.isEmpty() ) { log.warn("All server certificates were rejected; check MTWILSON_TLS_CERT_SHA1"); } } }