Andrew Barnes

4 minute read

Recently I was asked to help get a GitHub bot working with ServiceNow as the backend. What was engaging with the requirements for GitHub bots was the authentication type required. Looking at this handy blog from Thai Angsakulyanont, it was interesting to see that while I have done methods 1,2,3, the bot requires method 4, which was quite the wrench. We have explored JWT here on the blog before from none other than Dave Slusher. We won’t be doing quite the same as he was setting up an OAuth of JWT bearer type. Still, there are some setup similarities (that I wish I had remembered he documented and recreated during my explorations).

Let’s walk through the steps to get a JWT Provider set up and generate tokens for our GitHub bot!

Step 1 - Enable Plugin

To have JWT available as an authentication type, you must first enable the plugin. That plugin is “Integration - Multiple Provider Single Sign-On Installer” with id com.snc.integration.sso.multi.ui . After that is activated, JWT will be an option for authentication and inside the X509 Certificates.

Step 2 - Create a GitHub Application

Over in GitHub land you will need to create and register a new application. Make sure to note the App ID, and provide your instance in the callback URL field and the WebHook URL field.

Step 3 - Install App and get Private Key

In the setup screen, you can follow along with GitHubs instructions on how to generate a private key. This will download a PEM file to your local machine. Once that is done, install your bot in the repo/org you wish again using GitHubs lovely instructions.

Step 4 - Convert PEM to Java Key Store (JKS)

One of the things you will note if you take a look at the documentation for JWT in Docs, is the need for a Java Key Store (JKS). Note: the docs I link are only somewhat applicable since we are not setting up OAuth.

There are a few handy Unix commands that are going to be used to handle this conversion.

We will need a Cert to pair with our PEM, as a JKS isn’t complete without a certificate even though we don’t need one since all we need is the private key.

Create Dummy Cert - replace the all caps in all of the code blocks below

openssl req -new -key PRIVATEKEY.pem -days 365 -nodes -x509 -keyout OUTPUTNAME.key -out OUTPUTNAME.crt

Combine our PEM file and CRT to PKCS12

openssl pkcs12 -export -in OUTPUTNAME.crt -inkey PRIVATEKEY.pem -certfile OUTPUTNAME.crt -out OUTPUTCERT.p12

You will be prompted to set a password (to be used later)

Convert PKCS12 to JKS

keytool -importkeystore -srckeystore OUTPUTCERT.p12 -srcstoretype pkcs12 -destkeystore OUTPUTCERT.jks -deststoretype JKS

Now we have a JKS file that is ready to move into our ServiceNow instance!

Step 5 - Setup JWT Key and Provider in ServiceNow

We are leaving behind our local machine its time to dive into ServiceNow. Start by creating an x509 Certificate record.

x509.png

Attach the JKS you created locally, set the type to JKS and provide the Key Store password from Step 4.

Now you can create the JWT key record.

key_store.png

Choose RSA 256 and provide the password from Step 4 into the Signing Key field. The signing keystore will be the x509 record you just created.

Next, you will create the JWT Provider record.

provder.png

The signing configuration will be the key record we just generated and the expiry will be 600 seconds per GitHubs requirements.

Step 6 - Generate a token

Now that we have our JWT provider setup, we can leverage it to cook up our token to be used with the GitHub API’s for our bot! I created a flow designer action to handle this for me, but for the purposes of this blog, we will just look at doing this in a background script. Replace the two all apps items below with the AppID from GitHub and the sys_id of the JWT Provider.

var jwtAPI = new sn_auth.GlideJWTAPI();
var headerJSON = { typ: "JWT", alg: "RSA256"};
var header = JSON.stringify(headerJSON);
var gdt = new GlideDateTime();
gdt.addSeconds(6000);
//iss in line below needs to be changed if app id changes
var payloadJSON = { "iat": gs.now(), "iss": APPIDFROMGITHUB, "exp": gdt };
var payload = JSON.stringify(payloadJSON);

var jwtProviderSysId = "REPLACEWITHSYS_IDOFPROVIDER";
var jwt = jwtAPI.generateJWT(jwtProviderSysId, header, payload);

gs.info("JWT:" + jwt);

Profit!

Thank you for following along with me here. You can watch most of this process in the Live Coding Happy Hour that was done on this topic. Please let me know if you have any questions in the comments below.


Comments