/*
* Copyright (C) 2013 Intel Corporation
* All rights reserved.
*/
package com.intel.mtwilson.setup.tasks;
import com.intel.dcsg.cpg.crypto.RsaUtil;
import com.intel.dcsg.cpg.validation.Fault;
import com.intel.dcsg.cpg.x509.X509Builder;
import com.intel.dcsg.cpg.x509.X509Util;
import com.intel.mtwilson.My;
import com.intel.mtwilson.setup.AbstractSetupTask;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.List;
import org.apache.commons.io.IOUtils;
/**
* @author jbuhacoff
*/
public class CreateCertificateAuthorityKey extends AbstractSetupTask {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(CreateCertificateAuthorityKey.class);
private String caDistinguishedName = "CN=mtwilson-ca,OU=mtwilson";
public String getCaDistinguishedName() {
return caDistinguishedName;
}
public void setCaDistinguishedName(String distinguishedName) {
this.caDistinguishedName = distinguishedName;
}
@Override
protected void configure() throws Exception {
if( caDistinguishedName == null ) {
configuration("CA distinguished name is not configured");
}
getConfiguration().setString("mtwilson.ca.dn", caDistinguishedName);
}
@Override
protected void execute() throws Exception {
createCaKey();
}
private void createCaKey() throws NoSuchAlgorithmException, CertificateEncodingException, UnsupportedEncodingException, FileNotFoundException, IOException {
// create a new key pair
KeyPair cakey = RsaUtil.generateRsaKeyPair(2048); // throws NoSuchAlgorithmException
X509Builder builder = X509Builder.factory();
X509Certificate cacert = builder.selfSigned(caDistinguishedName, cakey).build();
if( cacert == null ) {
// log.error("Failed to create certificate"); // no need to print this, if the build failed there are guaranteed to be faults to print...
List<Fault> faults = builder.getFaults();
for(Fault fault : faults) {
log.error(String.format("%s%s", fault.toString(), fault.getCause() == null ? "" : ": "+fault.getCause().getMessage()));
}
return;
}
String privateKeyPem = RsaUtil.encodePemPrivateKey(cakey.getPrivate());
String cacertPem = X509Util.encodePemCertificate(cacert); // throws CertificateEncodingException
String combinedPrivateKeyAndCertPem = privateKeyPem + cacertPem;
byte[] combinedPrivateKeyAndCertPemBytes = combinedPrivateKeyAndCertPem.getBytes("UTF-8"); // throws UnsupportedEncodingException
byte[] cacertPemContent = cacertPem.getBytes("UTF-8");
try (FileOutputStream cakeyOut = new FileOutputStream(My.configuration().getCaKeystoreFile())) { // throws FileNotFoundException, IOException
IOUtils.write(combinedPrivateKeyAndCertPemBytes, cakeyOut); // throws IOException
} catch (Exception ex) {
log.error("Error creating CA key store file", ex);
}
try (FileOutputStream cacertsOut = new FileOutputStream(My.configuration().getCaCertsFile())) {
IOUtils.write(cacertPemContent, cacertsOut);
} catch (Exception ex) {
log.error("Error creating CA certificate file", ex);
}
}
@Override
protected void validate() throws Exception {
// make sure that we can load the ca key and certificate and that the cert has the right flags -
// remember that it may have been created elsewhere and imported so the code above to create it
// is not necessarily what happened.
if(My.configuration().getCaKeystoreFile().exists()) {
byte[] combinedPrivateKeyAndCertPemBytes;
try (FileInputStream cakeyIn = new FileInputStream(My.configuration().getCaKeystoreFile())) {
combinedPrivateKeyAndCertPemBytes = IOUtils.toByteArray(cakeyIn);
}
try {
PrivateKey cakey = RsaUtil.decodePemPrivateKey(new String(combinedPrivateKeyAndCertPemBytes));
log.debug("Read cakey {} from {}", cakey.getAlgorithm(), My.configuration().getCaKeystoreFile().getAbsolutePath());
}
catch(Exception e) {
log.debug("Cannot read private key from {}", My.configuration().getCaKeystoreFile().getAbsolutePath(), e);
validation("Cannot read private key from: %s", My.configuration().getCaKeystoreFile().getAbsolutePath());
}
try {
X509Certificate cacert = X509Util.decodePemCertificate(new String(combinedPrivateKeyAndCertPemBytes));
log.debug("Read cacert {} from {}", cacert.getSubjectX500Principal().getName(), My.configuration().getCaKeystoreFile().getAbsolutePath());
}
catch(Exception e) {
log.debug("Cannot read certificate from {}", My.configuration().getCaKeystoreFile().getAbsolutePath(), e);
validation("Cannot read certificate from: %s", My.configuration().getCaKeystoreFile().getAbsolutePath());
}
}
else {
validation("File not found: %s", My.configuration().getCaKeystoreFile().getAbsolutePath());
}
if(My.configuration().getCaCertsFile().exists()) {
byte[] cacertPemContent;
try (FileInputStream cacertsIn = new FileInputStream(My.configuration().getCaCertsFile())) {
cacertPemContent = IOUtils.toByteArray(cacertsIn);
}
try {
List<X509Certificate> certificates = X509Util.decodePemCertificates(new String(cacertPemContent));
log.debug("Read {} certificates from {}", certificates.size(), My.configuration().getCaCertsFile().getAbsolutePath());
}
catch(Exception e) {
log.debug("Cannot read certificates from {}", My.configuration().getCaCertsFile().getAbsolutePath(), e);
validation("Cannot read certificates from: %s", My.configuration().getCaCertsFile().getAbsolutePath());
}
}
else {
validation("File not found: %s", My.configuration().getCaCertsFile().getAbsolutePath());
}
}
}