Notifications

359 views

Abstract

The CCS Customer Endpoint is an HTTPS service that responds to a simple GET request for a customer’s proprietary key, with a “wrapped” version of said key.  This Endpoint will be polled regularly by ServiceNow, typically every 15 minutes.

Request protocol

a GET request is made to:

  • https://<customer.endpoint_host.com>/kek/<instance>/<key_id>

where:

  • <instance> is an alpha-numeric string, (ex. my_instance123)
  • <key_id> is an integer (ex. 456) 

with headers:

  • X-DB-Certificate: base 64 encoded X509 certificate

Response protocol (JSON)

Success example (http 200):

{ 
"keyId":0,
 "wrappedKey":"MDsFvB8........nziVTy2og5B4QVBw9lcA==",
"validUntil":"2019-10-10T00:22:43.037Z"
}

wrappedKey is a base64 encoded representation of the wrapped proprietary key, where the “wrapping” is done via the x509 encoded RSA public key available in the “X-DB-Certificate” request header.  The key must be 64 characters of hex (32 bytes hex-encoded).  The public key is attached to this article - snc-db-encrypt.ca.crt.txt (rename to remove .txt extension). The customer needs to validate the DBI endpoint using the certificate in the X-DB-Certificate header.  The certificate contains "tse_<instance_name>" so as part of check 'tse_' must be appended to the instance name before comparing. 

validUntil is an ISO8601 formatted timestamp, indicating the date at which the provided key expires.

Failure example (http non-200):


"error":"some error message detailing what went wrong" 
}

Response codes

  • 200 (success) when:
    • the endpoint successfully wrapped the proprietary key
  • 400 (bad request) when:
    • the URI does not match the /kek/<instance>/<key_id> pattern
  • 404 (resource not found) when:
    • <instance> is not recognized by the endpoint
    • <key_id> is not recognized by the endpoint
  • 500 (internal server error) when:
    • endpoint failed to wrap the proprietary key with ServiceNow’s public key for some reason.

Miscellaneous

Example Java class which can be used to wrap proprietary keys:

class RSAPublicKeyWrapper {
  
private final PublicKey publicKey;

  
RSAPublicKeyWrapper(HttpServletRequest request) throws Exception {
     
byte[] x509EncodedCertificate = Base64.getDecoder().decode(request.getHeader("X-DB-Certificate"));

     
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
     
InputStream in = new ByteArrayInputStream(x509EncodedCertificate);
     
X509Certificate cert = (X509Certificate)certFactory.generateCertificate(in);

     
X509EncodedKeySpec spec = new X509EncodedKeySpec(cert.getPublicKey().getEncoded());
     
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
      this
.publicKey = keyFactory.generatePublic(spec);
  
}

  
byte[] wrap(String proprietaryKey) {
     
try {
        
return getCipher(Cipher.ENCRYPT_MODE).doFinal(proprietaryKey.getBytes());
     
} catch (Exception e) {
        
throw new RuntimeException(e);
     
}
   }

  
private Cipher getCipher(int mode) throws Exception {
      Cipher cipher = Cipher.getInstance(
"RSA");
     
cipher.init(mode, publicKey);
      return
cipher;
  
}
}

Article Information

Last Updated:2020-04-20 09:44:46
Published:2020-04-20
snc-db-encrypt.ca.crt.txt