How to Call Canned (Builtin) Script Runner Scripts from a Script?

Phillip Ponzer [Cprime]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 14, 2014

I am attempting to use cURL/Python/anything to run one of Script Runner's built-in scripts, namely the Copy Project script. I am doing this on a computer that isn't the JIRA server, if that helps at all.

I followed the instructions from this answer to no avail:
https://answers.atlassian.com/questions/276778/how-can-i-remotely-trigger-a-groovy-script-on-my-jira-server

Here's the cURL command, which fills output2.html with the "Administrator Access" page:

curl "<JIRA BASE URL>/secure/admin/groovy/CannedScriptRunner.jspa"
 --user username:password
 --header "X-Atlassian-Token: no-check"
 --data "cannedScript=com.onresolve.jira.groovy.canned.admin.CopyProject"
 --data "cannedScriptArgs_FIELD_SOURCE_PROJECT=TESTOLD"
 --data "cannedScriptArgs_FIELD_TARGET_PROJECT=TESTNEW"
 --data "cannedScriptArgs_FIELD_TARGET_PROJECT_NAME=testnew"
 --data "cannedScriptArgs_Hidden_FIELD_SOURCE_PROJECT=TESTOLD"
 --data "cannedScriptArgs_Hidden_FIELD_TARGET_PROJECT=TESTNEW"
 --data "cannedScriptArgs_Hidden_FIELD_TARGET_PROJECT_NAME=testnew"
 --data "RunCanned=Run"
 --output output2.html

I have also tried getting a cookie with one cURL command and using that cookie in a second cURL command, which also doesn't work.

UPDATE #1:

Getting nowhere with cURL, I decided to give Python a try (also to no avail--it brings me to the "Administrator Access" page):

data = {"cannedScript": "com.onresolve.jira.groovy.canned.admin.CopyProject",
        "cannedScriptArgs_FIELD_SOURCE_PROJECT": "AFPAG1X",
        "cannedScriptArgs_FIELD_TARGET_PROJECT": "P67",
        "cannedScriptArgs_FIELD_TARGET_PROJECT_NAME": "Piper+test+4",
        "cannedScriptArgs_Hidden_FIELD_TARGET_PROJECT": "P67",
        "cannedScriptArgs_Hidden_FIELD_TARGET_PROJECT_NAME": "Piper+test+4",
        "cannedScriptArgs_Hidden_FIELD_SOURCE_PROJECT": "AFPAG1X",
        "cannedScript": "com.onresolve.jira.groovy.canned.admin.CopyProject",
        "RunCanned": "Run"
} cmd = "secure/admin/groovy/CannedScriptRunner.jspa" headers = {"content-type": "application/json", "X-Atlassian-Token":"no-check"} session = requests.session() result = session.post( "%s/%s" % ( JIRA_SERVER.url, cmd ), json.dumps( data ), headers = headers, auth = ( JIRA_SERVER.username, JIRA_SERVER.password ), verify = False )

UPDATE #2:

I found the following answer to be useful: https://answers.atlassian.com/questions/77474/how-can-i-use-curl-to-interact-with-websudo-in-jira-or-confluence

However, I'm stuck at the same spot as Vineetha is: I can now get cURL to authenticate with JIRA to get redirected to the right page, but I can't get cURL to submit the form! Any ideas?

Any help would be greatly appreciated! Thanks!

2 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

4 votes
Answer accepted
Phillip Ponzer [Cprime]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 15, 2014

Figured it out! I had to combine the following sources of cURL commands before I wound up with my solution!

  1. https://answers.atlassian.com/questions/77474/how-can-i-use-curl-to-interact-with-websudo-in-jira-or-confluence
  2. https://answers.atlassian.com/questions/276778/how-can-i-remotely-trigger-a-groovy-script-on-my-jira-server
  3. http://pastebin.com/8vVYbWB8

My solution:

#!/bin/bash

USERNAME=my_username
PASSWORD=my_password
JIRA_URL=http://my.jira.instance.com
COOKIES=cookies.txt
HEADER="X-Atlassian-Token: no-check"

echo Logging in...
curl -s -c "$COOKIES" -H "$HEADER" -d "os_username=$USERNAME" -d "os_password=$PASSWORD" -d "os_cookie=true" $JIRA_URL/login.jsp --output login.html

echo Authenticating as administrator...
curl -si -c "$COOKIES" -b "$COOKIES" -H "$HEADER" -d "webSudoPassword=$PASSWORD" -d "os_cookie=true" -d "webSudoIsPost=false" -d "authenticate=Confirm" $JIRA_URL/secure/admin/WebSudoAuthenticate.jspa --output auth.html

echo Copying project...
curl -s -b "$COOKIES" -H "$HEADER" -d "os_cookie=true" -d "webSudoIsPost=true" -d "cannedScript=com.onresolve.jira.groovy.canned.admin.CopyProject" -d "cannedScriptArgs_FIELD_SOURCE_PROJECT=OLD_PROJECT_KEY" -d "cannedScriptArgs_FIELD_TARGET_PROJECT=NEW_PROJECT_KEY" -d "cannedScriptArgs_FIELD_TARGET_PROJECT_NAME=New Project Name" -d "RunCanned=Run" --output output.html $JIRA_URL/secure/admin/groovy/CannedScriptRunner.jspa

echo Cleaning up...
rm $COOKIES

Rick Trudeau April 15, 2014

Nice work. I was just about to start looking into how to pass input variables, and you've saved me a lot of effort. Thanks.

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 16, 2014

Nice... it's in my todo list to write this up for the next major version. Unfortunately it will be somewhat different (simpler, but different).

1 vote
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 14, 2014

I don't know about the rest of it, but I think it should be nocheck, not no-check, even though the docn says otherwise.

Also not sure if you can use multiple --data args.

Phillip Ponzer [Cprime]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 14, 2014

It should be no-check, I just tried it without the dash and it sent me to a "XSRF Security Token Missing" page instead of the "Administrator Access" page.

Also, according to http://curl.haxx.se/docs/manpage.html#-d:

If any of these options is used more than once on the same command line, the data pieces specified will be merged together with a separating &-symbol.

However, I have also tried it with one --data argument &'d together and it gives me the same result (the "Administrator Access" page).

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 14, 2014
Phillip Ponzer [Cprime]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 14, 2014

When I right-clicked on the POST command and Copied it as cURL, I didn't receive any -X flags, just a bunch of -H flags, one really big --data flag, and a --compressed flag.

How should I be using the -X flag?

Phillip Ponzer [Cprime]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 15, 2014

Jamie, thanks for your help (and Script Runner)!

Bryan Karsh
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 21, 2014

Hi guys,

Thanks for these great examples. Had a question. I have curl running a script that gets the last login time for users. The console prints out tabs and line returns. However, in the curl response, I get the "\t" and "\n" in the output. Is there some way to interpolate these in the curl output? Can't figure it out. Below is the groovy script and bash script.

USERNAME=robot
PASSWORD=secret
JIRA_URL=https://my.jira.com
COOKIES=cookies.txt
HEADER="X-Atlassian-Token: no-check"

echo Logging in...
curl -x http://myproxy.corp.foobar.com:8080 -s -c "$COOKIES" -H "$HEADER" -d "os_username=$USERNAME" -d "os_password=$PASSWORD" -d "os_cookie=true" $JIRA_URL/login.jsp --output login.html

echo Authenticating as administrator...
curl -x http://myproxy.corp.foobar.com:8080 -si -c "$COOKIES" -b "$COOKIES" -H "$HEADER" -d "webSudoPassword=$PASSWORD" -d "os_cookie=true" -d "webSudoIsPost=false" -d "authenticate=Confirm" $JIRA_URL/secure/admin/WebSudoAuthenticate.jspa --output auth.html

echo Checking users...


SCRIPT_TO_RUN=last-login-test.groovy


curl -x http://myproxy.corp.foobar.com:8080 "https://my.jira.com/rest/scriptrunner/latest/user/exec/" -s -b "$COOKIES" -H "X-Atlassian-token: nocheck" -H "Origin: https://my.jira.com" -H "Accept-Encoding: gzip,deflate,sdch" -H "Accept-Language: en-US,en;q=0.8" -H "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36" -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" -H "Accept: application/json, text/javascript, */*; q=0.01" -H "Referer: https://my.jira.com/plugins/servlet/scriptrunner/console?section=script_console" -H "X-Requested-With: XMLHttpRequest" -H "Connection: keep-alive" --data "scriptFile=${SCRIPT_TO_RUN}&scriptText=" --compressed




echo Cleaning up...
rm $COOKIES

Bryan Karsh
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 21, 2014

Here is the groovy the above bash script calls:

import com.atlassian.jira.bc.security.login.LoginService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.user.util.UserUtil
import com.atlassian.crowd.embedded.api.CrowdService
import com.atlassian.crowd.embedded.api.UserWithAttributes
import java.sql.Timestamp

def result = ""

def groupNames = [
        'jira-users',
]

CrowdService crowdService = ComponentAccessor.crowdService
UserWithAttributes user
UserUtil userUtil = ComponentAccessor.userUtil
LoginService loginService = ComponentAccessor.getComponent(LoginService)

userUtil.getAllUsersInGroupNamesUnsorted(groupNames).findAll { it }.each {
    user = crowdService.getUserWithAttributes(it.getName())

    if (loginService.getLoginInfo(user.name).getLastLoginTime() > 0) {
        Long lastLoginTime = loginService.getLoginInfo(user.name).getLastLoginTime()
        Timestamp lastLoginTimeStamp = new Timestamp(lastLoginTime as long)
        result += user.getDisplayName() + "\t" + user.name + "\t" + user.getEmailAddress() + "\t" + user.isActive() + "\t" + lastLoginTimeStamp + "\t" + "\n"
    } else {
        if (loginService.getLoginInfo(user.name).getLastFailedLoginTime() > 0) {
            Long lastFailedTime = loginService.getLoginInfo(user.name).getLastFailedLoginTime()
            Timestamp lastFailedTimeStamp = new Timestamp(lastFailedTime as long);
            result += user.getDisplayName() + "\t" + user.name + "\t" + user.getEmailAddress() + "\t" + user.isActive() + "\t" + 'NULL' + "\t" + lastFailedTimeStamp + "\n"
        } else {
            result += user.getDisplayName() + "\t" + user.name + "\t" + user.getEmailAddress() + "\t" + user.isActive() + "\t" + 'NULL' + "\t" + 'NULL' + "\n"

        }


    }
}
result

Bryan Karsh
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 21, 2014

Thanks Jamie -- just wanted to make sure I wasn't going crazy. Fortunately, I am strong in the perl-fu, so I'll just roll it up my shell that way. :)

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 21, 2014

Your problem is the response is actually in json... the actual output is not just the script output. From running a script of "foo" the returned text is:

{"output":"foo"}

So you need to use a json parser to parse it, and then read the output key. Would seem like a good idea for the plugin to use content negotiation, so if you request text/plain, you just get the raw output. I'll raise a bug. Right now though you need to parse the response... perl/ruby/python make this trivial enough, in a shell script.

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
July 22, 2014

cool, created an issue anyway: https://jamieechlin.atlassian.net/browse/GRV-468

Danny van den Berg March 14, 2018

Nice work! Works even for Confluence with some small changes to call REST API.

Thanks!

TAGS
AUG Leaders

Atlassian Community Events