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!
Community moderators have prevented the ability to post new answers.
Figured it out! I had to combine the following sources of cURL commands before I wound up with my solution!
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
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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).
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Sometimes it's nocheck: https://docs.atlassian.com/atlassian-rest/2.4.0-alpha1/atlassian-rest-common/xref/com/atlassian/plugins/rest/common/security/jersey/XsrfResourceFilter.html
I don't see your -X POST, unless maybe that is inferred by using --data.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Jamie, thanks for your help (and Script Runner)!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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. :)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
cool, created an issue anyway: https://jamieechlin.atlassian.net/browse/GRV-468
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Nice work! Works even for Confluence with some small changes to call REST API.
Thanks!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.