/*
* Copyright (C) 2011-2012 Intel Corporation
* All rights reserved.
*/
package com.intel.mtwilson.crypto;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.intel.dcsg.cpg.crypto.HmacCredential;
import com.intel.dcsg.cpg.crypto.CryptographyException;
import com.intel.dcsg.cpg.crypto.RsaCredentialX509;
import com.intel.dcsg.cpg.crypto.SimpleKeystore;
import com.intel.mtwilson.KeystoreUtil;
import com.intel.mtwilson.ApiClient;
import com.intel.mtwilson.api.*;
import com.intel.mtwilson.datatypes.OsData;
import com.intel.dcsg.cpg.io.ByteArrayResource;
import com.intel.dcsg.cpg.io.ConfigurationUtil;
import com.intel.dcsg.cpg.io.Resource;
import com.intel.dcsg.cpg.tls.policy.TlsUtil;
import com.intel.dcsg.cpg.tls.policy.impl.InsecureTlsPolicy;
import com.intel.mtwilson.datatypes.ApiClientCreateRequest;
import com.intel.mtwilson.datatypes.OemData;
import com.intel.mtwilson.datatypes.Role;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.*;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.configuration.MapConfiguration;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* These tests use a temporary file for the keystore and use an embedded
* configuration to control the tests. To bootstrap your
* developer environment please use the code in the "Bootstrap" class.
* @author jbuhacoff
*/
public class KeystoreTest {
public static Properties config;
@BeforeClass
public static void configure() throws IOException {
// create a temporary keystore file for this test suite
File tmp = File.createTempFile("keystore", ".jks"); // IOException. // creates a temporary file
config = new Properties();
config.setProperty("mtwilson.api.baseurl", "https://10.1.71.134:8181");
config.setProperty("mtwilson.api.keystore", tmp.getAbsolutePath());
config.setProperty("mtwilson.api.keystore.password", "changeit123");
config.setProperty("mtwilson.api.key.alias", "mysecretapikey");
config.setProperty("mtwilson.api.key.password", "changeit123");
config.setProperty("mtwilson.api.ssl.verifyHostname", "false");
config.setProperty("mtwilson.api.ssl.requireTrustedCertificate", "true");
}
/*
* Performs an arbitrary api call, "listAllOS"...
* Fails if the keystore does not have the server's SSL certificate
*/
@Test
public void executeApiCall() throws MalformedURLException, ClientException, IOException, IOException, ApiException, ApiException, SignatureException {
// test API client against a server and require valid certs
URL url = new URL(config.getProperty("mtwilson.api.baseurl"));
Properties p = new Properties();
p.setProperty("mtwilson.api.keystore", config.getProperty("mtwilson.api.keystore"));
p.setProperty("mtwilson.api.keystore.password", config.getProperty("mtwilson.api.keystore.password"));
p.setProperty("mtwilson.api.ssl.requireTrustedCertificate", "true");
p.setProperty("mtwilson.api.ssl.verifyHostname", "false");
ApiClient c = new ApiClient(url, new HmacCredential("cloudportal@intel","nU8jTeJaFJZ7TJdMb4g4wAOljEHqwyFoRGvrsPjxrST8icOU"), p);
List<OsData> list = c.listAllOS();
System.out.println(String.format("Got list size %i", list.size()));
}
@Test
public void createNewKeystore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
File keystoreFile = new File(config.getProperty("mtwilson.api.keystore"));
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null, null);
KeystoreUtil.save(keystore, config.getProperty("mtwilson.api.keystore.password"), keystoreFile);
System.out.println("Created new keystore in "+keystoreFile.getAbsolutePath());
}
@Test
public void showCertificatesInKeystore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException, UnrecoverableEntryException {
KeyStore keystore = KeystoreUtil.open(new MapConfiguration(config));
Enumeration<String> aliases = keystore.aliases();
System.out.println("Certificates in keystore:");
int count = 0;
while(aliases.hasMoreElements()) {
count++;
String alias = aliases.nextElement();
System.out.println("Trusted certificate: "+alias);
X509Certificate cert = KeystoreUtil.loadX509Certificate(keystore, alias);
System.out.println("Subject: "+cert.getSubjectX500Principal().getName());
}
System.out.println(String.format("%d certificates", count));
}
/**
* Saves server's SSL certificates into keystore - assumes they are trusted.
* This is only sample code, in production you need to prompt the user to
* verify the fingerprint of the certificate before you add it, to prevent
* man-in-the-middle attacks.
* Since these are SSL certificates they are added to the keystore with the
* "SSL" trusted purpose tag in their alias.
* @throws MalformedURLException
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
* @throws IOException
*/
@Test
public void addServerSslCertificateToKeystore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException {
KeyStore keystore = KeystoreUtil.open(new MapConfiguration(config));
URL url = new URL(config.getProperty("mtwilson.api.baseurl"));
X509Certificate[] certs = TlsUtil.getServerCertificates(url);
String aliasBasename = "serverCert";
int certificateNumber = 0;
for(X509Certificate cert : certs) {
certificateNumber++;
String alias = String.format("%s%d (ssl)", aliasBasename, certificateNumber);
keystore.setCertificateEntry(alias, cert);
System.out.println("Added certificate to keystore: "+aliasBasename);
}
KeystoreUtil.save(keystore, config.getProperty("mtwilson.api.keystore.password"), new File(config.getProperty("mtwilson.api.keystore")));
}
@Test
public void createNewKeystoreWithServerSslCert() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableEntryException, KeyManagementException {
createNewKeystore();
showCertificatesInKeystore();
addServerSslCertificateToKeystore();
showCertificatesInKeystore();
}
/*
* Same as createNewKeystoreWithServerSslCert but uses the SimpleKeystore class.
*/
@Test
public void createNewKeystoreWithServerSslCertUsingSimpleKeystore() throws KeyManagementException, KeyStoreException, MalformedURLException, NoSuchAlgorithmException, IOException, CertificateException {
// create new keystore (if file does not exist and is writable it will be created when we save)
SimpleKeystore keystore = new SimpleKeystore(new File(config.getProperty("mtwilson.api.keystore")), config.getProperty("mtwilson.api.keystore.password"));
// list certificates
String[] aliases1 = keystore.listTrustedSslCertificates();
for(String alias : aliases1) { System.out.println("Certificate: "+alias); }
System.out.println(String.format("%d certificates", aliases1.length));
// add server ssl certificate
URL url = new URL(config.getProperty("mtwilson.api.baseurl"));
X509Certificate[] certs = TlsUtil.getServerCertificates(url);
String aliasBasename = "serverCert";
int certificateNumber = 0;
for(X509Certificate cert : certs) {
certificateNumber++;
String alias = String.format("%s%d", aliasBasename, certificateNumber);
keystore.addTrustedSslCertificate(cert, alias);
System.out.println("Added certificate to keystore: "+alias);
}
// show certificates again
String[] aliases2 = keystore.listTrustedSslCertificates();
for(String alias : aliases2) { System.out.println("Certificate: "+alias); }
System.out.println(String.format("%d certificates", aliases2.length));
// save keystore
keystore.save();
}
/*
@Test
public void testCreateKeystoreWithServerSslCertificate() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
// create a new keystore and save the new key into it
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null, null);
keystore.setKeyEntry("mykey", keypair.getPrivate(), "changeit".toCharArray(), new X509Certificate[] { certificate });
File tmp = File.createTempFile("keystore", ".jks"); // IOException. // creates a temporary file
KeystoreUtil.save(keystore, "changeit", tmp);
System.out.println("Keystore is in "+tmp.getAbsolutePath());
}
*/
@Test
public void testGetServerSslCerts() throws IOException, NoSuchAlgorithmException, KeyManagementException, CertificateEncodingException {
X509Certificate[] certs = TlsUtil.getServerCertificates(new URL("https://10.1.71.81:8181/AttestationService"));
for(X509Certificate cert : certs) {
System.out.println(String.format("Subject: %s", cert.getSubjectX500Principal().getName()));
System.out.println(String.format("Issuer: %s", cert.getIssuerX500Principal().getName()));
System.out.println(String.format("Not Before: %s", cert.getNotBefore().toString()));
System.out.println(String.format("Not After: %s", cert.getNotAfter().toString()));
byte[] certBytes = cert.getEncoded();
MessageDigest hashMd5 = MessageDigest.getInstance("MD5");
byte[] digestMd5 = hashMd5.digest(certBytes);
System.out.println(String.format("MD5: %s", new String(Hex.encodeHex(digestMd5))));
MessageDigest hashSha1 = MessageDigest.getInstance("SHA-1");
byte[] digestSha1 = hashSha1.digest(certBytes);
System.out.println(String.format("SHA-1: %s", new String(Hex.encodeHex(digestSha1))));
MessageDigest hashSha256 = MessageDigest.getInstance("SHA-256");
byte[] digestSha256 = hashSha256.digest(certBytes);
System.out.println(String.format("SHA-256: %s", new String(Hex.encodeHex(digestSha256))));
}
}
public static void main(String[] args) throws MalformedURLException, NoSuchAlgorithmException, KeyManagementException, UnsupportedEncodingException, IOException, ApiException, SignatureException, KeyStoreException, CertificateException, ClientException {
URL url = new URL("https://10.1.71.81:8181");
try {
// test API client against a server and require valid certs
Properties p = new Properties();
p.setProperty("mtwilson.api.ssl.requireTrustedCertificate", "true");
p.setProperty("mtwilson.api.ssl.verifyHostname", "false");
ApiClient c = new ApiClient(url, new HmacCredential("cloudportal@intel","nU8jTeJaFJZ7TJdMb4g4wAOljEHqwyFoRGvrsPjxrST8icOU"), p);
List<OsData> list = c.listAllOS();
System.out.println(String.format("Got list size %i", list.size()));
}
catch(javax.net.ssl.SSLPeerUnverifiedException e) {
System.out.println(String.format("SSL certificate for server %s is not trusted", url.toExternalForm()));
System.out.println("Add certificate to trust store and try again? (Y/N) ");
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String saveCertAndTryAgain = in.readLine().trim();
if( saveCertAndTryAgain.toUpperCase().startsWith("Y") ) {
// download server SSL certificates
X509Certificate[] serverCertificates = TlsUtil.getServerCertificates(url);
// create a new temporary trust store and add those certificates
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null, null);
String aliasBasename = "tmp";
int certificateNumber = 0;
for(X509Certificate cert : serverCertificates) {
certificateNumber++;
String alias = String.format("%s%i", aliasBasename, certificateNumber);
keystore.setCertificateEntry(alias, cert);
}
File tmp = File.createTempFile("keystore", ".jks"); // IOException. // creates a temporary file
KeystoreUtil.save(keystore, "changeit", tmp);
System.out.println("Keystore is in "+tmp.getAbsolutePath());
// try the call again
Properties p = new Properties();
p.setProperty("mtwilson.api.ssl.requireTrustedCertificate", "true");
p.setProperty("mtwilson.api.ssl.verifyHostname", "false");
p.setProperty("mtwilson.api.truststore", tmp.getAbsolutePath());
ApiClient c = new ApiClient(url, new HmacCredential("cloudportal@intel","nU8jTeJaFJZ7TJdMb4g4wAOljEHqwyFoRGvrsPjxrST8icOU"), p);
List<OsData> list = c.listAllOS();
System.out.println(String.format("Got list size %i", list.size()));
}
}
/*
*
mtwilson.api.clientId=
mtwilson.api.secretKey=
*
System.out.println("URL: "+baseurl.toExternalForm());
System.out.print("Root password: ");
*
*/
}
@Test
public void testCreateUserInResource() throws MalformedURLException, IOException, ApiException, CryptographyException, ClientException, KeyStoreException, CertificateEncodingException, SignatureException, FileNotFoundException, NoSuchAlgorithmException, UnrecoverableEntryException {
String username = "rksavinx";
String password = "savinorules";
URL fullUrl = new URL("https://10.1.71.134:8181/mtwilson/v1/");
//URL fullUrl = new URL("http://localhost:8080/v1");
String[] roles = { Role.Whitelist.toString(),Role.Attestation.toString(),Role.Security.toString()};
ByteArrayResource certResource = new ByteArrayResource();
SimpleKeystore keystore = KeystoreUtil.createUserInResource(certResource, username, password, fullUrl, roles);
System.out.println("DONE");
}
}