1. 检索 certificate 属性

使用 MOB(托管对象浏览器)检索证书信息,在浏览器地址栏输入下面的地址(其搜索路径为 ServiceInstance-> content -> ha-folder-root -> ha-datacenter -> ha-folder-host -> ha-compute-res -> ha-host -> config):

https://192.168.1.xxx/mob/?moid=ha-host&doPath=config

该地址进入的是 ESXi 主机配置信息对象 HostConfigInfo 的界面,里面有个 certificate 属性,如下图:

esxi 见证 ova esxi证书_ESXi

如上图,该 certificate 是一个十进制的字节数组,需要将该数组转为以十六进制展示的那种形式。

esxi 见证 ova esxi证书_esxi 见证 ova_02

2. 根据主机名称获取 certificate 属性值
/**
   * @Title: getCertificate
   * @Description: 获取主机证书
   * @param hostName
   * @return
   * @throws RuntimeFaultFaultMsg
   * @throws InvalidPropertyFaultMsg
   */
  @Override
  public ArrayOfByte getCertificate(String hostName)
      throws RuntimeFaultFaultMsg, InvalidPropertyFaultMsg {

    // certificate属性
    String[] propsArr = new String[] {"config.certificate"};

    ManagedObjectReference hostMor = getMorByObjectName("HostSystem", hostName);

    // 获取属性对应的实体
    Map<String, Object> result = retrieveEntityProps(hostMor, propsArr);

    ArrayOfByte certificate = null;
    // 遍历结果
    for (String key : result.keySet()) {
      if ("config.certificate".equals(key)) {
        certificate = (ArrayOfByte) result.get(key);
      }
    }
    return certificate;
  }

该方法获取到的 certificate 是十进制数组,结果如下:

45
45
45
45
45
66
69
71
73
78
32
67
.
.
.
3. 将十进制数组 certificate 转为十六进制

其中的证书字节数组转换只用到 byte2HexStr() 这个方法,其他互转方法当作一个记录供学习。

import java.net.URL;
import java.util.List;

import com.vmware.vim25.ArrayOfByte;

import cn.vms.VmClientSession;
import cn.vms.VmClientSessionFactory;
import cn.vms.entity.EsxiConnectionEntity;

/**
 * @ClassName: HexUtil
 * @Description: 10进制byte数组与16进制byte数组互转
 */
public class HexUtil {

  /** 16进制中的字符集 */
  private static final String HEX_CHAR = "0123456789ABCDEF";

  /** 16进制中的字符集对应的字节数组 */
  private static final byte[] HEX_STRING_BYTE = HEX_CHAR.getBytes();

  /**
   * 10进制字节数组转换为16进制字节数组
   *
   * byte用二进制表示占用8位,16进制的每个字符需要用4位二进制位来表示,则可以把每个byte
   * 转换成两个相应的16进制字符,即把byte的高4位和低4位分别转换成相应的16进制字符,再取对应16进制字符的字节
   *
   * @param b 10进制字节数组
   * @return 16进制字节数组
   */
  public static byte[] byte2hex(byte[] b) {
    int length = b.length;
    byte[] b2 = new byte[length << 1];
    int pos;
    for (int i = 0; i < length; i++) {
      pos = 2 * i;
      b2[pos] = HEX_STRING_BYTE[(b[i] & 0xf0) >> 4];
      b2[pos + 1] = HEX_STRING_BYTE[b[i] & 0x0f];
    }
    return b2;
  }

  /**
   * 16进制字节数组转换为10进制字节数组
   *
   * 两个16进制字节对应一个10进制字节,则将第一个16进制字节对应成16进制字符表中的位置(0~15)并向左移动4位,
   * 再与第二个16进制字节对应成16进制字符表中的位置(0~15)进行或运算,则得到对应的10进制字节
   * @param b 10进制字节数组
   * @return 16进制字节数组
   */
  public static byte[] hex2byte(byte[] b) {
    if (b.length % 2 != 0) {
      throw new IllegalArgumentException("byte array length is not even!");
    }

    int length = b.length >> 1;
    byte[] b2 = new byte[length];
    int pos;
    for (int i = 0; i < length; i++) {
      pos = i << 1;
      b2[i] = (byte) (HEX_CHAR.indexOf(b[pos]) << 4 | HEX_CHAR.indexOf(b[pos + 1]));
    }
    return b2;
  }

  /**
   * 将16进制字节数组转成10进制字符串
   *
   * @param b 16进制字节数组
   * @return 10进制字符串
   */
  public static String hex2Str(byte[] b) {
    return new String(hex2byte(b));
  }

  /**
   * 将10进制字节数组转成16进制字符串
   *
   * @param b 10进制字节数组
   * @return 16进制字符串
   */
  public static String byte2HexStr(byte[] b) {
    String hexStr = new String(b);
    // int data = Integer.parseInt(sb);
    // return Integer.toHexString(data);
    return hexStr;
  }

  // 获取 Certificate 字节数组
  public static ArrayOfByte getCertificateTest() throws Exception {
    URL url = new URL("https://192.168.1.xxx/sdk/vimService?wsdl");
    EsxiConnectionEntity esxiConnectionEntity = new EsxiConnectionEntity();
    esxiConnectionEntity.setUrl(url);
    esxiConnectionEntity.setUserName("root");
    esxiConnectionEntity.setPassword("******");

    VmClientSession vmClientSession = VmClientSessionFactory.bulidVmClientSession(esxiConnectionEntity, "userId");
    ArrayOfByte certificate =
        vmClientSession.getEsxiApi().getInventoryInfoApi().getCertificate("localhost.localdomain");

    vmClientSession.close();

    return certificate;
  }

  // 测试
  public static void main(String[] args) throws Exception {

    ArrayOfByte certificateByteArr = getCertificateTest();

    List<Byte> certlist = certificateByteArr.getByte();

    byte[] certb = new byte[certlist.size()];
    for (int i = 0; i < certlist.size(); i++) {
      // System.out.println(certlist.get(i));
      certb[i] = certlist.get(i);
    }

    System.out.println(byte2HexStr(certb));

  }

}

结果如下:

-----BEGIN CERTIFICATE-----
MIID8jCCAtqgAwIBAgIHAKlNwVk6VDANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQK
ExBWTXdhcmUgSW5zdGFsbGVyMB4XDTE3MDYwMjA3MDAxNFoXDTI4MTIwMTA3MDAx
NFowgfoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQH
EwlQYWxvIEFsdG8xFDASBgNVBAoTC1ZNd2FyZSwgSW5jMS4wLAYDVQQLEyVWTXdh
cmUgRVNYIFNlcnZlciBEZWZhdWx0IENlcnRpZmljYXRlMSowKAYJKoZIhvcNAQkB
Fhtzc2wtY2VydGlmaWNhdGVzQHZtd2FyZS5jb20xHjAcBgNVBAMTFWxvY2FsaG9z
dC5sb2NhbGRvbWFpbjEwMC4GCSqGSIb3DQEJAhMhMTQ5NjM4NjgxNCw1NjRkNzc2
MTcyNjUyMDQ5NmU2MzJlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
qyEZkKgZDfj04z3NLmQOuX4OAbbNHZYztU1Hp0C53fPS66cLVBvn0nKuk4PvNIZl
5dYcPBR+ifFrynM3z4dA7GXvHtCmSXnhdO7tyF8YxQkAHC4NcmKUcpwQ7B3lDtMf
eDO86IcX1nAMLjHXRDDppQOZAQg33SWne9uEbFPKTLZuvplhbE4JbBmRjdn39XfG
i2cL/QIN9XvxGmJluPI9DPlD3ijC83SgARRq8euL8ZSQiJRniy+iRnbxw6pMdR0K
ac+dqC13UBabVtFaveZdHY27w7foetG4weLqfx/9Qosl3re7cOKiLez/IQXHjo+i
qs/a63HXf5tSE4CevEE3IwIDAQABo1swWTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE
sDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwIAYDVR0RBBkwF4IVbG9j
YWxob3N0LmxvY2FsZG9tYWluMA0GCSqGSIb3DQEBCwUAA4IBAQBlUL1d71h3S8DP
Tpz0FnfWlMd2dtuqnRtGvQz09nhCwQ2AUJv5mgcM34SuVM2HwyVl7MQwBc2s3dZg
gz+G6q5btKF9BQrheDxgfzKQrEO3mY11jh7+HREIR2usfoI5IPAoSBsmy/zbtkvr
2RZAjf/DTCW4uuIF0v0uU7V5Y5oFqetRH4yM3euPzWfaxEEeBxVV/UqiZyw306oo
n7C4JobuZH2Ht5kklunG9jMmigDLjAXoyXMP/eWRHc9p4pMUfypI8Pdz2l9mS+oC
W5ynFXXNKVVf2SkBj6Wf4+NPIe3OzL42YqCtK7YY+EW1GBZGAia6aYYa1hpTB/53
41zp9DyZ
-----END CERTIFICATE-----

然后可以通过命令行或其他工具根据该证书生成 ESXi 主机的 thumbprint。



参考:
Java 10进制byte数组与16进制byte数组互转 及 在DES加解密中的使用