Trying to create a new script via the API

hollanderb
New Contributor

I'm trying to use the REST API to create a new script, but I've encountered some confusion regarding the way it is supposed to be used. The documentation says that to create a new script, you 'POST' to <jss_url>/JSSResource/scripts/id/{id} where {id} is the "Id value to filter by". However if I am using this API call to create a new script, it does not have an associated id. Is anyone able to shed some light on the proper way to do this?

Thank you

12 REPLIES 12

mm2270
Legendary Contributor III

Generally speaking when creating objects and using PUT or POST, you need to first create a valid xml file the REST API will take, then use POST to upload the file.
As far as the ID to use, that's a little trickier. You may need to first use a GET command to pull down a list of all your scripts by their IDs and sort the IDs in numerical order, and use the next available number for the ID of the new script.

stevewood
Honored Contributor II
Honored Contributor II

@hollanderb not sure if this will work for creating a script, but you can use this URL to create a computer record:

https://myjss.com:8443/JSSResource/computers/id/0

This was spoken by Bryson Tyrell (@brysontyrrell) in this discussion:

API and POST command

Not sure if it will work, but worth a try.

GaToRAiD
Contributor II

@hollanderb I'm confused by the question, usually you use a script to communicate with JSS via the API, not use the API to create a script. Here is an example of what i'm referring too.

#!/bin/sh

jssUser=JSSAPIUsername
jssPass='passwordForJSS'
jssHost=https://localhost:8443/

xml="<?xml version="1.0" encoding="ISO-8859-1" ?>
    <computer>
    </computer>"

theJSSresponse=$( /usr/bin/curl 
--header "Content-Type: text/xml; charset=utf-8" 
--data "${xml}" 
--request GET 
--connect-timeout 5 
--max-time 10 
--user ${jssUser}:${jssPass} 
--insecure 
${jssHost}JSSResource/computers/"id"/$1 2> /dev/null )

This will return information you request from the variable xml. But as you can see my variable is blank so it will return all information. Is this what you are trying to do?

hollanderb
New Contributor

Sorry if my question was unclear. To elaborate a bit more, I'm trying to leverage git hooks to push modified or newly created scripts to JSS. The goal is to be able to commit all code to a git repository and have any changes automatically be pushed to JSS. Where I'm running into a problem is when a new script is created in the git repository, I want to use the API to create a new script on JSS.

chriscollins
Valued Contributor

@hollanderb When you are creating a new object via the API, you use zero as the ID I believe.

GaToRAiD
Contributor II

@hollanderb ok, now i see what you are referring to.

So you can basically use my code to do it, and the "id" is referring to the id of the script. Each one gets an id number based on when it was created. The first one created is obviously #1, and so on so forth.

The easiest way to tell what is the number you need to use next is, go to a script in jss. Then look at the url bar.

For example.

https://casperurl:8443/scripts.html?id=100&o=r

The id of this script is 100.

mm2270
Legendary Contributor III

I can see some value in being able to create new script objects in the JSS via the API. Its somewhat limited but it may be valuable in certain use cases.

I just threw something together very quickly after pulling down one of our simple scripts from our JSS to examine how they appear in the API. The test I ran with this worked and created a new script called "script name.sh under our category of "Scripts" with an ID of 241 (previously 240 was the highest ID)

#!/bin/bash

jssURL="https://jss.company.com/JSSResource/scripts"
apiUser="apiuser"
apiPass="apipass"

last_script_id=$( curl -H "Accept: application/xml" -sfku "${apiUser}:${apiPass}" "${jssURL}" 2>&1 | xmllint --format - | awk -F'>|<' '/<id>/{print $3}' | sort -n | tail -1 )

new_script_id=$((last_script_id + 1))

echo "new script id will be: $new_script_id"

echo '<?xml version="1.0" encoding="UTF-8"?>
<script>
    <id>241</id>
    <name>script name.sh</name>
    <category>Scripts</category>
    <filename>script name.sh</filename>
    <info/>
    <notes/>
    <priority>Before</priority>
    <parameters/>
    <os_requirements/>
    <script_contents>#!/bin/sh

echo "This is my test script"

exit 0</script_contents>
</script>' > /private/tmp/script_${new_script_id}.xml

## Test the xml file to make sure its valid
xmllint /private/tmp/script_${new_script_id}.xml
if [ $? == 0 ]; then
    echo "XML is valid. Uploading"
    curl -skfu "${apiUser}:${apiPass}" ${jssURL}/id/$new_script_id -X POST -T /private/tmp/script_${new_script_id}.xml

    echo "POST exit result: $?"
else
    echo "XML creation failed. Exiting"
    exit 1
fi

The script then shows up in my JSS when I refresh the scripts page:
dc47d84edc714039ae33ecf9a41277c9
31dd39ac74cb41d9b83347fef972cf0c

Hope that helps. Edit: Whoops. Forgot the script tags.

chriscollins
Valued Contributor

@hollanderb Ok, I just double checked and if you post the new object via the API with id 0, it will create the object at the newest available number for you and then send back a response with the id # it created the new object with so you can manipulate it via put later.

mm2270
Legendary Contributor III

@chriscollins may be correct. Instead of doing what I did above and grabbing the next available ID, try just using id 0 and see if it works. I haven't tested that, but I seem to remember reading somewhere that that is the proper way to do it. It would be nice if the API documentation mentioned things like this, but often its missing a lot of important details.

GaToRAiD
Contributor II

@mm2270 agree with you on the documentation, like if you do a put in JSS, it actually copies the whole record and puts ur information in, then submits it to the db instead of just the info you asked it to put....

chriscollins
Valued Contributor

I often go back to Bryson's unofficial api doc as a reference as if anybody knows other than the developer its probably him: [https://bryson3gps.wordpress.com/the-unofficial-jss-api-docs/](hhttps://bryson3gps.wordpress.com/the-unofficial-jss-api-docs/)

The relevant excerpt:

POST takes XML data and creates a new JSS object for a resource. A successful POST returns a status code of 201 and a response containing the ID of the new object. When you are using POST on a resource you should always use the URI “/resource/id/0″ in your request. While many of the resources list supporting POST for key-values besides ID number, “/id/0″ is a special URI that will always create the new object at the next available ID number for that resource helping avoid errors and the need on your part to track what the next available ID is.

hollanderb
New Contributor

Thank you! Sending a POST with ID 0 worked. I agree, they really need to document things like that. Thank you for all of your effort!