- Post History
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
2 hours ago - edited 2 hours ago
Bring Your Own Key to ServiceNow KMF — Part 2: Importing Your Key
This is Part 2 of a three-part series on using your own encryption key inside ServiceNow's Key Management Framework. Part 1 covered the mental model, the role you need, and setting up the instance's RSA unwrapping key. Part 3 covers encrypting from script.
With the instance able to accept imported keys, we can build a module and get your own AES key into it.
Build your module
Key Management > Cryptographic Modules > Create New, then add a Specification:
| Field | Value |
|---|---|
| Purpose | Symmetric Data Encryption/Decryption |
| Algorithm | AES 256 GCM (or CBC) |
| Origin | Import from web service |
| Key alias | must be unique across all modules |
Then set the module to Published and Default module access policy to Track.
⚠️ Key operations silently do nothing on a Draft module. No error, no message, key version stays -1. Publish first. A duplicate key alias produces the same silent failure — worth checking if key generation appears to do nothing at all.
Note that module records cannot be deleted, and non-Enterprise instances cap at five. Name them deliberately the first time.
Wrap your key
Encrypt your AES key against the certificate from Part 1:
openssl pkeyutl -encrypt -pubin \
-inkey <(openssl x509 -in kmf_import.crt -pubkey -noout) \
-pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 \
-in your_aes.key -out aes_wrapped.bin # 512 bytes for RSA-4096
Verify the digest was not silently downgraded — some OpenSSL builds ignore an unsupported -pkeyopt and fall back to SHA-1 OAEP. Decrypt the result back with the .pem and compare hashes before going further. A mismatch here surfaces much later as an unexplained decryption failure.
Post it
POST /api/sn_kmf/key/import?cryptoSpecSysID=<spec sys_id>
Content-Type: application/octet-stream
Body: the wrapped bytes (raw, not base64)
⚠️ cryptoSpecSysID is mandatory and appears in no documentation. Without it you get "No cryptoSpecSysID specified in request params". The endpoint declares consumes: application/octet-stream, so send raw bytes rather than base64.
If your instance uses SSO, basic auth on REST may be disabled — in which case the simplest route is your browser's console on a logged-in session, passing window.g_ck as the X-UserToken header.
Activate it
A successful POST creates the key in generated state. It is not in use yet.
⚠️ KMF will not activate a second key of the same type while one is active. Suspend the existing key first, then activate yours. Confirm with:
var k = new GlideRecord('sys_kmf_module_key');
k.addQuery('crypto_module.name', 'CONTAINS', 'your_module');
k.query();
while (k.next()) {
gs.print(k.getUniqueValue() + ' | ' + k.getValue('key_lifecycle_state') +
' | ' + k.getValue('origin'));
}
You want exactly one active, with origin import_from_webservice.
This same suspend-then-activate step is how key rotation works later, so it is worth getting comfortable with now.
Part 3: encrypting from script, the output envelope, and a reusable Script Include.
