Another Solution for Uploading Scripts

Some time ago I wrote Scriptorium to keep the scripts on your Mac in sync with the same scripts on your Jamf Pro server.

Thanks to the excellent tool jctl from the people at the Marriot Library of the University of Utah I have a simple solution using their tool and git hooks so when you push to your repo the script is updated in Jamf Pro.

Install jctl from their repo at https://github.com/univ-of-utah-marriott-library-apple/jctl/wiki/Installing. Once you have done that you need the hook in .git/hooks in your repo. Call it pre_push

#!/bin/bash
if [[ $(git diff origin/main@{1} origin/main --name-status | grep -c ${name_of_script}) > 0 ]]; then
var=$(cat "${path_of_script}")
/opt/homebrew/bin/jctl scripts -i ${id_of_script} -u script_contents="${var}" --use-the-force-luke
fi

pre-push means that the hook runs after you have typed git push and before the actual push occurs. If you want to you can stop the push from happening by returning non-zero from your script. I don’t do that as I’m not doing any testing in the hook.

name_of_script is, of course, the name of the script. path_of_script is the name of, and path to, the script. id_of_script is the ID in Jamf Pro of the script, you can find it in the URL of the script.

I use direnv to set the variables. You could hard code them but that seems like actual work. Now every time you do a git push the script is sent to your server.

Let me know if you find this useful.

JNUC is Next Week

From https://publicdomainpictures.net/

JNUC 2023 in Austin is just around the corner. Come see my presentation on shell programming. https://bit.ly/jnuc2023.

From 5-line extension attributes to security shell scripts that run to over a thousand lines, shell programming is a key part of macOS administration. We can all write better code.

Through examples of shell code attendees will learn:

  • How to avoid bad code
  • How to make code comprehensible
  • How to write resilient code

Solve The New York Times Spelling Bee

I am currently visiting my brother in Maryland and his wife, Michele, likes doing the NYT Spelling Bee. It’s a word puzzle where you get 7 letters and one of the 7 is required, with a minimum length of 4 letters. Letters can be repeated in a word. There is at least one word that uses every character.

This raises the question, given a list of words what is the shortest piece of code to give all possible answer words. I think I’m close with a single awk command.

bee() { ;  awk  "/^[$1]{4,}$/ && /$2/" /usr/share/dict/words ; }

You call the function bee <letters> <letter required>. For example the puzzle on September 12 is bee gviotnp t.

As I cannot get the list of words the NYT is using I am using the word list on my Mac which returns more words than the NYT. If I could find a shorter word list closer to the NYT list it would improve the output.

Looking for a new role

Excuse me for a minute, I’m going to do some shameless self promotion.

Back in March last year I asked for your help in finding me a new role. That search did end up with me getting a job. Unfortunately it wasn’t the good fit I was looking for and I will be finishing up there in four weeks.

I’m currently hard at work looking for my next role. I think my time at my current employer is coming to an end and to become a better engineer I need to move to somewhere new. I need a place that is a better fit.

If you have read my blog, visited my GitHub repositories, or seen some of my presentations you already know a bit about me. I’m a decent engineer with pretty good skills at Python and the shell and I get the job done. I’m a quick learner and a voracious reader of tech sites.

But let me quote from my CV.

“I design and build systems that allow organisations to deploy and secure Macintosh computers, iPhones and iPads.”

“My personal mission is to build a back end that supports well designed, well built, and fuss free devices for the end user. I’d like to work for an organisation that has the same goal and believes Apple devices are a great way of delivering that.”

If you know of an organisation looking for a Client Platform Engineer or Device Management Engineer then I’d love you to drop me a note at honestpuck@gmail.com. If you want my CV to pass along you can grab it on my Github repo at https://bit.ly/tonyw2023.

Thanks for letting me advertise to you (again).

Using the NIST macOS_security project with Jamf Pro

I have just completed a project to update the security posture for a Mac fleet and wrote up a HOWTO use the NIST project with Jamf Pro. It is an impressive tool and well maintained by a number of people.

My HOWTO details policies, profiles, extension attributes and scripts. I hope people find it useful. Check it out at https://github.com/Honestpuck/NIST-macos-security-HOWTO

Designing Scriptorium

I just released Scriptorium, a small console program. Here are some notes on how I used argparse to do that.

We need a function to parse our arguments. Parsing is taking the line of words from the command line and processing them to extract the structure and meaning. The term ‘word’ can be fraught with complexity on the shell command line but a simple definition is any set of characters delimited by a space or matching quotes.

Scriptorium has a simple structure, scriptorium <command> [<argument>]. Some commands don’t have any arguments, for some arguments are entirely optional and for others arguments are required. But let’s start building that parser.

    """ build our command line parser """
    parser = argparse.ArgumentParser(
        epilog="for command help: `scriptorium <command> -h`"
    )
    subparsers = parser.add_subparsers(description="", required=True)

You can also see we are starting to build some help in ‘epilog’ – this is the final line printed when you run scriptorium --help. Then we need to have some code to parse each individual commands arguments. This is a subparser.

Continue reading

Scriptorium – a better way for Jamf Pro scripts

A little while ago I became extremely annoyed by a bunch of scripts in my Jamf Pro instance that weren’t properly named and didn’t have proper author comments.

What’s an easy way to rename a dozen scripts and edit twenty? There really isn’t one so instead of doing it by hand I decided I wanted a software system that made it easy. Yes, I know, spending a chunk of your spare time writing 750 lines of Python (it was actually 950 till I did some serious refactoring) rather than a day doing it manually might seem a little, well, silly. I know, I have a problem, I’m working on it.

Scriptorium is the result. A Python script that uses a combination of two directories and two git repositories to provide versioning, tracking, and backup while adding an easier to use interface for editing the scripts.

I’d never built a script with an extensive command line interface. Python’s argparse library makes it incredibly easy. Not only does it allow you to quickly put together the commands and options in the process it builds your help system and quickly structures your code with each command requiring it’s own function.

As Scriptorium leverages git adding a git module to zsh and the git lens extension to Visual Studio Code adds even further benefits.

I’ve tried to make the README file as comprehensive as possible so go give that a read and grab a copy on Github

You might also find me speaking about it at JNUC2021.

Another PatchBot update

Since the last time I wrote about PatchBot I’ve made a few improvements to the Production processor.

  • Moved decision logic from Move.py into the processor.
  • Added the recipe variable delta to specify days between test and production.
  • Added the recipe variable deadline to set the Self Service deadline.
  • Added defaults for delta and deadline to the top of Production.py to ease customization

Both the recipe variables are optional. It’s now possible to use the -k option of Autopkg to quickly move a package from test into production with a short Self Service deadline if you need to:

autopkg run Firefox.prod -k "delta=-1" -k "deadline=2"

The above will immediately move the Firefox package into the production patches and set a deadline of two days. We set a delta of -1 because the system used for command line arguments doesn’t allow us to tell the zero we get when there was no command line argument and the zero we get when we set it as the variable value. A value of -1 has the same effect as zero. If the difference between the date the package was put into test and today is zero then a difference greater than or equal to zero, and greater than or equal to -1, are both true.

I’ve also added a tool to the #patchbot channel in the MacAdmins Slack that posts to the channel whenever I push new code to the GitHub repository.