/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.intel.mtwilson.agent.citrix; import com.intel.mountwilson.as.common.ASException; import com.intel.mountwilson.ta.data.hostinfo.HostInfo; import com.intel.mtwilson.agent.HostAgent; import com.intel.dcsg.cpg.crypto.RsaUtil; import com.intel.mtwilson.datatypes.TxtHostRecord; import com.intel.mtwilson.model.Aik; import com.intel.mtwilson.model.Nonce; import com.intel.mtwilson.model.Pcr; import com.intel.mtwilson.model.PcrIndex; import com.intel.mtwilson.model.PcrManifest; import com.intel.dcsg.cpg.crypto.Sha1Digest; import com.intel.mtwilson.model.TpmQuote; import com.xensource.xenapi.Types; import java.io.IOException; import java.io.StringWriter; import java.net.MalformedURLException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.apache.xmlrpc.XmlRpcException; /** * * @author stdalex */ public class CitrixHostAgent implements HostAgent{ private CitrixClient client; private Logger log = LoggerFactory.getLogger(getClass()); public CitrixHostAgent(CitrixClient client) { this.client = client; } @Override public boolean isTpmEnabled() { return true; } @Override public boolean isEkAvailable() { return true; } @Override public boolean isAikAvailable() { return true; } @Override public boolean isAikCaAvailable() { return false; } @Override public boolean isDaaAvailable() { return true; } @Override public X509Certificate getAikCertificate() { throw new UnsupportedOperationException("Not supported"); } @Override public X509Certificate getAikCaCertificate() { throw new UnsupportedOperationException("Not supported"); } @Override public String getHostInformation() { throw new UnsupportedOperationException("Not supported yet."); } @Override public String getVendorHostReport() throws IOException { throw new UnsupportedOperationException("Not supported yet."); } @Override public TpmQuote getTpmQuote(Aik aik, Nonce nonce, Set<PcrIndex> pcr) { throw new UnsupportedOperationException("Not supported yet."); } @Override public TxtHostRecord getHostDetails() throws IOException { long getHostInfoStart = System.currentTimeMillis(); //throw new UnsupportedOperationException("Not supported yet."); TxtHostRecord record = new TxtHostRecord(); HostInfo info; try { info = this.client.getHostInfo(); } catch(NoSuchAlgorithmException | KeyManagementException | MalformedURLException | Types.XenAPIException | XmlRpcException ex){ log.error("getHostDetails getHostInfo caught: " + ex.getMessage()); throw new IOException("Cannot get Citrix host info: "+ex.getMessage(), ex); } record.HostName = client.hostIpAddress; record.IPAddress = client.hostIpAddress; record.Port = client.port; record.BIOS_Name = info.getBiosOem(); record.BIOS_Version = info.getBiosVersion(); record.BIOS_Oem = info.getBiosOem(); record.VMM_Name = info.getVmmName(); record.VMM_Version = info.getVmmVersion(); record.VMM_OSName = info.getOsName(); record.VMM_OSVersion = info.getOsVersion(); record.AddOn_Connection_String = client.connectionString; record.Processor_Info = info.getProcessorInfo(); record.AIK_Certificate = null; long getHostInfoStart2 = System.currentTimeMillis(); log.debug("CitrixClient: Time taken to get host information - " + (getHostInfoStart2 - getHostInfoStart) + " milliseconds"); // Nov 19, 1013: Since AIK Cert is not needed by functions that call getHostDetails and also there is a separate function to // retrieve the AIK Cert, we will comment this out. /* try { record.AIK_Certificate = client.getAIKCertificate(); } catch(Exception ex){ log.error("getHostDetails getAikCert caught: " + ex.getMessage()); } long getHostInfoStart3 = System.currentTimeMillis(); log.debug("CitrixClient: Time taken to get AIK Cert - " + (getHostInfoStart3 - getHostInfoStart2) + " milliseconds");*/ return record; } /* * Format should look something like this * <?xml version='1.0' encoding='UTF-8'?> * <Host_Attestation_Report Host_Name="10.1.70.126" vCenterVersion="5.0" HostVersion="5.0"> * <PCRInfo ComponentName="0" DigestValue="1d670f2ae1dde52109b33a1f14c03e079ade7fea"/> * <PCRInfo ComponentName="17" DigestValue="ca21b877fa54dff86ed5170bf4dd6536cfe47e4d"/> * <PCRInfo ComponentName="18" DigestValue="8cbd66606433c8b860de392efb30d76990a3b1ed"/> * </Host_Attestation_Report> */ @Override public String getHostAttestationReport(String pcrList) throws IOException { long getAttReportStart1 = System.currentTimeMillis(); String attestationReport = ""; XMLOutputFactory xof = XMLOutputFactory.newInstance(); XMLStreamWriter xtw; StringWriter sw = new StringWriter(); try { xtw = xof.createXMLStreamWriter(sw); xtw.writeStartDocument(); xtw.writeStartElement("Host_Attestation_Report"); xtw.writeAttribute("Host_Name",this.client.hostIpAddress); xtw.writeAttribute("vCenterVersion", "5.0"); xtw.writeAttribute("HostVersion", "5.0"); //xtw.writeAttribute("TXT_Support", tpmSupport.toString()); long getAttReportStart2 = System.currentTimeMillis(); log.debug("CitrixClient: before calling to get quote info - " + (getAttReportStart2 - getAttReportStart1) + " milliseconds"); HashMap<String, Pcr> pcrMap = client.getQuoteInformationForHost(pcrList); long getAttReportStart3 = System.currentTimeMillis(); log.debug("CitrixClient: Time taken to get quote info - " + (getAttReportStart3 - getAttReportStart2) + " milliseconds"); Iterator it = pcrMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry pairs = (Map.Entry)it.next(); xtw.writeStartElement("PCRInfo"); Pcr pcr = (Pcr)pairs.getValue(); xtw.writeAttribute("ComponentName",pcr.getIndex().toString()); xtw.writeAttribute("DigestValue", pcr.getValue().toString()); xtw.writeEndElement(); it.remove(); // avoids a ConcurrentModificationException } xtw.writeEndElement(); xtw.writeEndDocument(); xtw.flush(); xtw.close(); attestationReport = sw.toString(); long getAttReportStart4 = System.currentTimeMillis(); log.debug("CitrixClient: before sending the quote info - " + (getAttReportStart4 - getAttReportStart3) + " milliseconds"); } catch (XMLStreamException ex) { // Logger.getLogger(CitrixHostAgent.class.getName()).log(Level.SEVERE, null, ex); log.error("Cannot get host attestation report", ex); } log.debug("getHostAttestationReport report:" + attestationReport); return attestationReport; } @Override public boolean isIntelTxtSupported() { return true; } @Override public boolean isIntelTxtEnabled() { return true; } @Override public boolean isTpmPresent() { return true; } @Override public X509Certificate getEkCertificate() { throw new UnsupportedOperationException("Not supported yet."); } /* BEFORE * -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvNEz3+TStAAndHTc1qwT NGvZYyB7DD1FshQf+mbQUGJ9HccOXNn5oHB7fWQjODjlDrYyCs7FclSMTLxA3lHX 98QWeWHL2O8t8qrJQQEUWZITmr/ddiNJOOvMeYF0K5if4m84vjgx/pTwwAVyU0Yo MMXPnRozO8o7zSyRsH4jixALDugrsveEjLQI/cIEFvNjqlhyfumHyJKywNkMH1oJ 4e/f89FkpeDV694lsLs1jguuLLnvroXYJ5Uzeos+F0Pj1zFDUvhWrjVwxsUfAxS8 5uFGTUm6EEl9XiKwi+mgg8ODrY5dh3uE2yKB2T1Qj8BfK55zB8cYbORSsm6/f6Bi BwIDAQAB -----END PUBLIC KEY----- * AFTER * -----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvNEz3+TStAAndHTc1qwTNGvZYyB7DD1FshQf+mbQUGJ9HccOXNn5oHB7fWQjODjlDrYyCs7FclSMTLxA3lHX98QWeWHL2O8t8qrJQQEUWZITmr/ddiNJOOvMeYF0K5if4m84vjgx/pTwwAVyU0YoMMXPnRozO8o7zSyRsH4jixALDugrsveEjLQI/cIEFvNjqlhyfumHyJKywNkMH1oJ4e/f89FkpeDV694lsLs1jguuLLnvroXYJ5Uzeos+F0Pj1zFDUvhWrjVwxsUfAxS85uFGTUm6EEl9XiKwi+mgg8ODrY5dh3uE2yKB2T1Qj8BfK55zB8cYbORSsm6/f6BiBwIDAQAB-----END PUBLIC KEY----- */ @Override public PublicKey getAik() { PublicKey pk = null; try { String crt = client.getAIKCertificate(); log.debug(" crt == " + crt); pk = RsaUtil.decodePemPublicKey(crt); //client.getAIKCertificate().replace(X509Util.BEGIN_PUBLIC_KEY, "").replace(X509Util.END_PUBLIC_KEY, "").replaceAll("\n","").replaceAll("\r",""); } catch(Exception ex){ log.error("getAik caught: " + ex.getMessage()); } return pk; } @Override public PcrManifest getPcrManifest() throws IOException { PcrManifest pcrManifest = new PcrManifest(); String pcrList = "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24"; HashMap<String, Pcr> pcrMap = client.getQuoteInformationForHost(pcrList); log.info("CitrixHostAgent: getQuoteInformationForHost done"); Iterator it = pcrMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry pairs = (Map.Entry)it.next(); Pcr pcr = (Pcr)pairs.getValue(); pcrManifest.setPcr(new Pcr(PcrIndex.valueOf(Integer.parseInt(pcr.getIndex().toString())), new Sha1Digest(pcr.getValue().toString()))); //it.remove(); // avoids a ConcurrentModificationException } log.info("CitrixHostAgent: created PcrManifest"); return pcrManifest; } @Override public Map<String, String> getHostAttributes() { HashMap<String,String> hm = new HashMap<>(); // Retrieve the data from the host and add it into the hashmap HostInfo hostInfo; try { hostInfo = client.getHostInfo(); log.debug("Successfully retrieved the details of the host ruuing OS {}.", hostInfo.getOsName()); } catch (NoSuchAlgorithmException | KeyManagementException | MalformedURLException | Types.XenAPIException | XmlRpcException ex) { log.error("Unexpected error during retrieval of the host properties. Details : {}", ex.getMessage()); } try { // Currently we are just adding the UUID of th host. Going ahead we can add additional details hm.put("Host_UUID", client.getSystemUUID()); } catch(NoSuchAlgorithmException | KeyManagementException | Types.XenAPIException | XmlRpcException ex){ throw new ASException(ex); } return hm; } @Override public void setAssetTag(com.intel.dcsg.cpg.crypto.Sha1Digest tag) throws IOException { try { client.setAssetTag(tag); } catch(Types.XenAPIException | XmlRpcException | NoSuchAlgorithmException | KeyManagementException e) { log.error("Unexpected error while setting asset tag", e); throw new IOException(e); } } }