Skip to content

JNUC2019 Intro and Overview

Chris Lasell edited this page Sep 24, 2019 · 13 revisions

Welcome to ruby-jss

Jamf Pro's Classic API provides RESTful, programmatic access to much of what's available in the Jamf Pro web interface, in either JSON or XML format.

While the API's existence is a boon for automating lots of Jamf Pro-related tasks, using it via bash scripts can be unwieldy, hard to grasp, and difficult to troubleshoot and maintain.

Take, for example, the task of changing the assigned user for all computers in a smart group

bash

GROUP_NAME='myGroupName'
NEW_COMPUTER_USER='jbleaux'
NEW_COMPUTER_USER_REAL_NAME='Jeaux Bleaux'

API_USER="api_username"
read -p "API pw for $API_USER: " API_PW

API_URL_BASE="https://jss.server:8443/JSSResource"

raw_group_xml=`curl -H 'Accept: application/xml' -sk -u "${API_USER}:${API_PW}" -X GET "${API_URL_BASE}/computergroups/name/${GROUP_NAME}"`

member_count=`echo "$raw_group_xml" | xmllint --xpath 'count(/computer_group/computers/computer)' -`

for (( i=1; i <= $member_count; i++ )); do
  computer_id=`echo "$raw_group_xml" | xmllint --xpath "/computer_group/computers/computer[$i]/id/text()" -`

  change_xml="<computer><location><username>$NEW_COMPUTER_USER</username><realname>$NEW_COMPUTER_USER_REAL_NAME</realname></location></computer>"

  curl -H 'Content-Type: application/xml' -u "${API_USER}:${API_PW}" -X PUT "${API_URL_BASE}/computers/id/${computer_id}" -d "$change_xml"
done

ruby using ruby-jss

require 'ruby-jss'

GROUP_NAME = 'myGroupName'
NEW_COMPUTER_USER = 'jbleaux'
NEW_COMPUTER_USER_REAL_NAME = 'Jeaux Bleaux'

JSS.api.connect server: 'jss.server', user: 'api_username', pw: :prompt

computer_group = JSS::ComputerGroup.fetch name: GROUP_NAME

computer_group.member_ids.each do |comp_id|
  computer = JSS::Computer.fetch id: comp_id
  computer.username = NEW_COMPUTER_USER
  computer.real_name = NEW_COMPUTER_USER_REAL_NAME
  computer.save
end

Which one would your mother understand more easily?

Not only your mother, which one will you understand more easily in 2 years, when you need to make some changes to the script or adapt it for some other purpose? Or your co-workers who need to work with it while you're on vacation trekking in the Himalayas?

When using ruby-jss, you don't have to worry about the details of the connection headers, insecure use of the password on a command-line, parsing or formatting XML or JSON - All of that is handled 'under the hood' for you. You can focus on the objects in your JSS - the computers, devices, groups, policies, packages, profiles, and so on. Your code will reflect them and their attributes at a conceptual level, increasing the writability, readability, and maintainability of your code.

Ruby's syntax may be a bit different from bash, but it isn't hard to learn, especially when you have API tasks to automate.

Not only will it be easier to write programs to automate repeated tasks, you can also use ruby-jss with Interactive Ruby, a.k.a. irb to act as a sort of 'shell' to your Jamf Pro server, allowing you to easily perform on-off tasks using the Classic API

Today's Lab

Today we're going to do just that.

We'll use irb and ruby-jss to connect to a Jamf Pro server and do things in realtime.

The things we do in irb are directly translatable to writing programs to run as needed. Just like bash code can be run live in a shell, or executed from a file, so can ruby be run live in irb, or exectuted from a file; the code is the same in both situations.

Here's what we'll cover:

  • installing ruby-jss and launching irb
  • ruby basics
    • collections: Arrays & Hashes
    • iterators
  • ruby-jss basics
    • connecting to the API
    • listing objects
    • fetching objects
    • changing and updating objects
    • deleting objects
  • real-life examples
    • updating extension attribute values
    • disabling all policies RIGHT NOW!!
    • ...
  • security considerations
  • QuickLook at the documentation, and how to read it.

More advanced stuff we won't cover in the lab, but should be mentioned:

  • Client-side coding
  • Scoping
  • Group and Search criteria
  • Multiple simultaneous API connections
Clone this wiki locally