Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

ServiceNow Jira Attachment Integration

ashik1
Kilo Guru

Hi All,

We all know John's poc work on ServiceNow-jira integration is one of the best references for integrating these tools - poc link

We do come across a requirement to manage file transfer as well. Many people have posted solutions for the same but none worked (at least for me it didn't work as expected) so I have tried to enhance the code of others from when they have left and below code works for me.

Requirements
Mid Server, Powershell installed in mid

Process Flow

  • Pick a file from SNow --> convert it to base64 --> dump the file in mid server in its original format
  • pick a file from mid server --> upload it to Jira --> delete uploaded file using Powershell

Code

/********************************************************************************************************************/
/********************************* Code to transfer file to mid-server ****************************************/
/********************************************************************************************************************/

Script Type: Mid Server Script Include
Name: JiraIntegration
Script:

var JiraAttachment = Class.create();
JiraAttachment.prototype = {
initialize: function () {
/* Set up the Packages references */
this.File = Packages.java.io.File;
this.FileOutputStream = Packages.java.io.FileOutputStream;
this.HttpClient = Packages.org.apache.commons.httpclient.HttpClient;
this.UsernamePasswordCredentials = Packages.org.apache.commons.httpclient.UsernamePasswordCredentials;
this.AuthScope = Packages.org.apache.commons.httpclient.auth.AuthScope;
this.GetMethod = Packages.org.apache.commons.httpclient.methods.GetMethod;

/* Set up the parameters */
this.verbose = probe.getParameter("verbose");
this.filepath = probe.getParameter("filepath");
this.filename = probe.getParameter("filename");
this.encodedData = probe.getParameter('encodedData');
this.debug("verbose -- filepath -- filename : "+this.verbose + ' -- ' + this.filepath + ' -- ' + this.filename);
},

/* Function to create new file and write data in target path*/
saveToFile: function(targetPath)
{
this.debug("Initiating file save function");
var f = new this.File(targetPath); // create new file
var inputStream = this.encodedData;
var fout = new this.FileOutputStream(f);
this.StringUtil = Packages.com.glide.util.StringUtil;
var data = this.StringUtil.base64DecodeAsBytes(inputStream); // convert base64 to original format
fout.write(data); // write data to newly created file
fout.close();
inputStream.close();
result = "File successfully created : "+this.filepath+this.filename;
this.debug(result);
},

/* Function to debug in mid-server log*/
debug: function (m)
{
if (this.verbose == "true") {
ms.log("Jira Attachment: " + m);
}
},

/* Execute the Probe*/
execute: function()
{
var saveRes = this.saveToFile(this.filepath+this.filename);
return result;
},
type : "JiraAttachment"
};

/********************************************************************************************************************/

/* Background Script to trigger above script include*/

Script:
var gr = GlideRecord('sys_attachment');
gr.addQuery('sys_id', <sysid_of_attachment>);
gr.query();
if (gr.next())
{
var sa = new GlideSysAttachment();
var binData = sa.getBytes(gr);
var encData =GlideStringUtil.base64Encode(binData);
var jspr = new JavascriptProbe(<midserver_name>);
jspr.setName(<Any_name_of_js_probe>); // This can be any name 
jspr.setJavascript("var ddr = new JiraAttachment(); res= ddr.execute();");
jspr.addParameter("verbose","true");
jspr.addParameter("filepath", <path_to_save_file>)); // eg, D://ServiceNow//JiraAttachment// This is optional, if not added, file will be created at rool i.e midserver's agent folder
jspr.addParameter("filename",gr.file_name);
jspr.addParameter("encodedData",encData);
jspr.create();
gs.print('Completedeck Mid Server log');
}

/********************************************************************************************************************/
/********************************** Code to upload file to jira ****************************************/
/********************************************************************************************************************/
Script Type: PowerShell script in mid-server
Name: JiraIntegration.ps1
Script: 

#
# (c) Ashik Narayan
#
# This script is related to "ServiceNow-Jira Integration" in Service Now
# This script attach file to Jira issue and delete fiel at source path (windows machine)

Param([string]$jira_base_url, [string]$jira_issue, [string]$file_path, [string]$file_name)

$jira_base_url = $null
$jira_issue = $null
$file_path = $null
$file_name = $null

if(test-path env:\SNC_jira_base_url) {
$jira_base_url=$env:SNC_jira_base_url
}

if(test-path env:\SNC_jira_issue) {
$jira_issue=$env:SNC_jira_issue
}

if(test-path env:\SNC_file_path) {
$file_path=$env:SNC_file_path
}

if(test-path env:\SNC_file_name) {
$file_name=$env:SNC_file_name
}

$wc = new-object System.Net.WebClient
#$wc.Headers.Add("Authorization", "Basic $([System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $<jira_user>, $<jira_password>))))")
#$wc.Headers.Add("Authorization", "<credentials_of_jira_account_in_basic>") //  after your testing, convert the credentials of jira account to basic authentication and replace with above line
$wc.Headers.Add("X-Atlassian-Token", "nocheck")
$wc.UploadFile($jira_base_url+"/rest/api/2/issue/"+$jira_issue+"/attachments", $file_path+$file_name)

Write-Host "Jira Attachment: Attachment Successful" $file_name

Remove-Item $file_path$file_name

Write-Host "Jira Attachment: File deleted successfully" $file_name

/********************************************************************************************************************/

/* Background Script to trigger above powershell script*/

Script: 
var payload = new GlideXMLDocument('parameters');
this.attachmentAddParametersToPayload(payload, 'skip_sensor', true);
this.attachmentAddParametersToPayload(payload, 'probe_name', 'Jira - MidServerToJira'); // this can be any name
this.attachmentAddParametersToPayload(payload, 'script.ps1', <path_of_powershell_script>)); // eg.D://ServiceNow//Script//JiraAttachment.ps1
this.attachmentAddParametersToPayload(payload, 'powershell_param_jira_base_url', <jira_instance_url>));
this.attachmentAddParametersToPayload(payload, 'powershell_param_jira_issue', <jira_issue>);
this.attachmentAddParametersToPayload(payload, 'powershell_param_file_path', <path_of_file_to_upload>); eg. D://ServiceNow//JiraAttachment//
this.attachmentAddParametersToPayload(payload, 'powershell_param_file_name', <name_of_file>); eg. abc.jpg
this.attachmentCreateECCEntry(payload.toString());

function attachmentAddParametersToPayload(payload, name, value) {
var element = payload.createElement('parameter');
element.setAttribute('name', name);
element.setAttribute('value', value);
},

function attachmentCreateECCEntry(payload) {
var eccgr = new GlideRecord('ecc_queue');
eccgr.initialize();
eccgr.agent = 'mid.server.'+<name_of_midserver>);
eccgr.topic = 'Powershell';
eccgr.name = 'Jira - MidServerToJira'; // this can be any name
eccgr.payload = payload;
eccgr.queue = 'output';
eccgr.state = 'ready';
this.outputq = eccgr.insert();
}

17 REPLIES 17

Hi Ashik

 

Really thankful for all your help but I am getting a strange error while executing the Powershell probe by populating the ECC queue with the topic name as Powershell . I am getting a kind of authentication error somehow which looks like below , somehow the Mid server is not able to make a correct call to the JIRA web service . Even though if I am executing the powershell script manually , it does run and makes the required upload to the JIRA Ticket from the same Server where the Mid Server is installed .

We changed the Mid Server Service to be executed by someone who has the admin rights , also gave the credentials inside the Credentials module but none of them works .

Below is the error which I am getting inside the Powershell Probe ECC queue .

 

Authentication failure with the local MID server service credential.</error><error>Failed to access target system.  Please check credentials and firewall settings on the target system to ensure accessibility: The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.</error><debug_info>{"debug_info":[{"No target":{"creds_failed_trying_local_mid_cred":true,"credentials_attempted":[{"credential_type":"Windows","credential_name":"Hendrik_admin","credential_order":"100","credential_success":false,"credential_id":"009a79e1dbba2f402f2829da4b961975"}],"local_mid_credential_success":false,"connection_parameters":{"credential_types":["Windows"]}}}]}</debug_info>

Hi Ashik ,

 

Did you use any specific Mid Server parameters that we need to take care of currently I am using the below :-

 

mid.powershell.local_mid_service_credential_fallback --> false

mid.powershell.use_credentials --> true

mid.property.powershell.command.script.parameter_passing --> true

mid.use_powershell --> true

 

Also now I am getting the below error after the credentials error is gone .

<?xml version="1.0" encoding="UTF-8"?><results probe_time="3094" result_code="4"><result><error/><error>Windows PowerShell is in NonInteractive mode. Read and Prompt functionality is not available.</error></result>

 

Can you suggest as to what might be the issue here . I have been searching a lot but to no success .

Hi,

 

Have you modified any parameter you passing or using exact same script I pasted?

Rocky10
Tera Contributor

I can manually run the PowerShell successfully from the midserver but not from the background script you provided to trigger the PowerShell.

<results probe_time="3352" result_code="2">
<result>
<error>
Failure(s) with available Windows credentials from the instance.
</error>
<error>
The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
</error>
</result>

Thank you for the article.  I'm experiencing the same issue (Authentication failure...).  I've checked my mid server configuration parameters and I have everything listed, except the "mid.property.powershell.command.script.parameter_passing --> true".  This parameter is not available for selection.  Do I have to create it?

I'm able to manually execute the PS script successfully.

Any thoughts on the issue would be helpful.  Thank you.

Rick