
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
Why integrate ServiceNow and Jira and why oAuth 1.0
Jira is a project management tool. Many company use Jira to manage projects across the organization. They also use ServiceNow to manage their IT Service Management, HR Management, Security Operations etc. Now the organizations have integrated ServiceNow with Jira using Basic authentication. But due to security concerns, they want to move away from Basic to oAuth.
The limitation in Jira is, it doesn’t support oAuth 2.0. There is an enhancement request (https://jira.atlassian.com/browse/JRASERVER-43171) still pending since 2015 and we can’t expect it to be implemented in the near future. So the only integration you can implement with Jira is oAuth 1.0.
On the other hand, ServiceNow deprecated oAuth 1.0 since Geneva release and they currently only support oAuth 2.0.
How did we build this custom oAuth Integration?
We followed the below link which provides examples to build your own script to perform the oAuth integration.
https://developer.atlassian.com/server/jira/platform/oauth/
But the instructions and examples don’t work well for integrating with ServiceNow.
So, we had to build our own custom code. Building the script was not so easy. The most challenging job was to generate the signature and the message header, that needs to be sent along with every request to Jira.
The initial few steps are straightforward and can be implemented by following steps in https://developer.atlassian.com/server/jira/platform/oauth/.
- Generate Public and Private Keys
The first thing you need to do is to generate the public and private key. To do so, you can follow Step1 in https://developer.atlassian.com/server/jira/platform/oauth/.
Provide the public key to the Jira Admin, who can set up an application for ServiceNow in Jira using the public key and provide you with a Consumer Key. You will need the consumer key in later steps, so keep that safe.
- Generate certificates in Servicenow supported format
Now here comes another problem. ServiceNow does not support pkcs8. But it does support pkcs12 and jks. So what we would like to do is convert the certificates to a p12 file. Instructions in step 1, generate the following files. Jira_privatekey.pem, jira_publickey.pem and jira_privatekey.pcks8.
To generate the p12, you need the jira_privatekey.pem and jira_publickey.pem file. Create a copy of jira_privatekey.pem, which will only have the private key (jira_privatekey_copy.pem). Add the public key from jira_publickey.pem to the same file after the RSA Private Key section as shown below.
-----BEGIN RSA PRIVATE KEY-----
<Private Key>
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
<Public Key>
-----END CERTIFICATE-----
Then run the following command to generate the pkcs file.
openssl pkcs12 -export -in jira_privatekey_copy.pem -out jira_privatekey.p12
- Add the certificates to ServiceNow
Once the pkcs file is generated, Navigate to System Definition->Certificates and create a record with type as PKCS12 Key Store and attach the p12 file to the record and save it.
- Generate Access Token
The next step is to generate the Access Token, which you would need to perform API operations in Jira. To generate the Access Token and token secret, follow step 2 & 3 in https://developer.atlassian.com/server/jira/platform/oauth/.
- Build the message header
Once you have the access token, use below function in ServiceNow to generate your header.
Store the access token, token secret and consumer key in a property file to access in the script.
In oAuth 1.0, you need to generate a signature base string and sign it with RSA-SHA1.
The first tough job was to build the base string.
I tried many custom code such as jsrsasign to sign the base string using RSA-SHA1, but it was very complicated. I almost gave up. But luckily I found this community question https://community.servicenow.com/community?id=community_question&sys_id=d2b987e5db5cdbc01dcaf3231f96... which led me to a function CertificateEncryption. Yes, ServiceNow has a new function CertificateEncryption which can sign base string using RSA-SHA1 encryption. I used it in below function and BINGO!!!. I was able to generate the signature. From here, the job was simple.
function generateHeader(method,endPoint)
{
var accessToken = gs.getProperty('<access token property name>');
var verificationCode = gs.getProperty('<token secret property name>');
var consumerKey = gs.getProperty('<consumer key property name>');
var signatureMethod = "RSA-SHA1";
var timestamp = Math.round((new Date()).getTime() / 1000.0);
var nonce = this.randomString(10);
var endPointParamStr = '';
// If the endpoint has parameters, split them and add as parameter in base string.
if (endPoint.indexOf('?')>-1)
{
var endPointArray = endPoint.split('?');
endPoint = endPointArray[0];
var endPointParam = endPointArray[1].split(',');
for (var i=0;i<endPointParam.length;i++)
{
endPointParamStr += encodeURIComponent(endPointParam[i]+"&");
}
}
var signatureBaseString = method+"&"+encodeURIComponent(endPoint) + "&";
if (endPointParamStr!='')
signatureBaseString += endPointParamStr;
signatureBaseString += encodeURIComponent("oauth_consumer_key="+consumerKey+"&");
signatureBaseString += encodeURIComponent("oauth_nonce="+nonce+"&");
signatureBaseString += encodeURIComponent("oauth_signature_method="+signatureMethod+"&");
signatureBaseString += encodeURIComponent("oauth_timestamp="+timestamp+"&");
signatureBaseString += encodeURIComponent("oauth_token="+accessToken+"&");
signatureBaseString += encodeURIComponent("oauth_token_secret="+verificationCode+"&");
signatureBaseString += encodeURIComponent("oauth_version=1.0");
var ce = new CertificateEncryption();
// For PKCS
var signature = ce.sign("<sys id of the certificate>", "1", "", "SHA1withRSA", signatureBaseString);
var header = "OAuth ";
header = header + "oauth_consumer_key=\""+consumerKey+"\"";
header = header + ", ";
header = header + "oauth_nonce=\""+nonce+"\"";
header = header + ", ";
header = header + "oauth_signature=\""+encodeURIComponent(signature)+"\"";
header = header + ", ";
header = header + "oauth_signature_method=\""+signatureMethod+"\"";
header = header + ", ";
header = header + "oauth_timestamp=\""+timestamp+"\"";
header = header + ", ";
header = header + "oauth_token=\""+accessToken+"\"";
header = header + ", ";
header = header + "oauth_token_secret=\""+verificationCode+"\"";
header = header + ", ";
header = header + "oauth_version=\""+"1.0"+"\"";
return header;
}
- Use the generateHeader to build API requests
To call the above function from your script, you can use this.generateHeader('GET',jiraURL). You need to pass the method name such as GET,PUT,POST etc and the End Point URL. The header generated from the above function should be passed in ‘Authorization’ tag.
function syncIndJIRATicket() {
var syncJIRA = new sn_ws.RESTMessageV2('JIRA Integration', 'Sync Issue');
syncJIRA.setEccParameter("skip_sensor","true");
var jiraEndPoint = syncJIRA.getEndpoint();
var jira = new GlideRecord("sn_si_jira_issue");
jira.addQuery('u_jira_id',event.parm2);
jira.query();
if(jira.next()){
var jiraURL = jiraEndPoint+jira.u_jira_id;
syncJIRA.setEndpoint(jiraURL);
//Generate Header and set the Authorization tag
syncJIRA.setRequestHeader('Authorization',this.generateHeader('GET',jiraURL));
var JIRAResponse = syncJIRA.execute();
var JIRAData = JSON.parse(JIRAResponse.getBody());
if (JIRAData.errors)
{
gs.info('Failed to sync JIRA ticket with following error: '+JSON.stringify(JIRAData.errors));
}
else
{
gs.info('Successfully pulled jira ticket information ');
}
}
}
This is it. It took me 10-12 days to find out the solution. I know many of you are still using basic auth since there is no oAuth 1.0 in ServiceNow and pretty sure you wouldn’t want to spend so many days to identify a solution for this. I hope this helps you and saves you time and give you a good solution.
#jiraintegration#jiraoauth1.0
- 1,890 Views
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.