Duo Labs EFIgy -- can it be turned into an extension attribute?

stevenjklein
Contributor II

I just finished reading this recently-released report: The Apple of Your EFI: Mac Firmware Security Research

They've written a Python tool that checks a Mac's firmware version to see if it's up-to-date.

It's a command-line tool that, as written, requires some interaction.

If this could be automated, an extension attribute could let Jamf users generate a report of Macs with out-of-date firmware. (One possibility: Have the Python script generate a file which can be read by a bash script.)

I don't know Python, or I'd try and tackle this myself.

Anyone else think this is worthwhile?

The Python script can be found here: EFIgyLite_cli.py

18 REPLIES 18

Not applicable

About to download it and play with it a bit - if I can get an EA working I'll report back.

mm2270
Legendary Contributor II

Looks like the script supports a quiet flag -q or --quiet, and you can use it with the log flag to send the stdout messages to the log file. The EA can probably pick up the info from there I would think.

Not applicable

Yeah - wasn't able to get the log to work correctly at first, but deleting (or better, commenting-out) lines 299-303 will remove the prompt.

I don't know how to format an EA with multiple results well though - we should be getting something like this as the output from the script:

`

EFI firmware version check: [] SUCCESS - The EFI Firmware you are running (MP61.0116.B46) is the expected version for the OS build you have installed (16G29) on your MacPro6,1 Highest build number check: [] SUCCESS - You are running the latest build number (16G29) of the OS version you have installed (10.12.6) Up-to-date OS check: [+] SUCCESS - You are running the latest major/minor/micro version of the OS you have installed (10.12.6)

I'm not comfortable enough in python to know how to format the multiple lines returned, but shouldn't be hard if you know what you're doing (I think!).

Bruienne
New Contributor II

Feel free to post a PR to the EFIgy repo with any changes to the code that would make it more EA-friendly, we want to make this tool as useful as possible for everyone regardless of their management tools. Thanks for trying it out!

cwaldrip
Valued Contributor

I have a question though about out of date EFI firmware though? Is it still possible to get the correct firmware to install?

benbass
New Contributor III

I created a package that drops the EFIgyLite_cli.py and the cacert.pem locally (having the package use it's resources folder so you don't have to play with /tmp/ or cleaning up files) and then use the -q and -l flags to write out the log. I then grab the log and rename it to a known value. I then have an EA that will grab just the EFI firmware version check info and grab that entire line into an EA. I haven't rolled the policy out to everyone yet, but I figured we could test and then see about getting the info across the fleet.

Not applicable

@benbass - Any chance of sharing the EA piece?

I did a little preliminary testing and had issues with getting the logging to work, but I probably spent about 2 minutes if that on it before getting distracted. I know management is interested in getting the data - sounds like your approach would make sense and be easier than trying to re-write the script into an EA itself.

troyewebster
New Contributor III

@benbass yep I’d also be interested in this approach ... sounds perfect for what I’m trying to accomplish

RobertHammen
Valued Contributor II

@cwaldrip Firmware is now embedded in OS installers/updates, not available standalone.

It's possible to extract the FirmwareUpdate.pkg from the 10.12.6 Combo Update (using SUS Inspector). I've simply added this package to a Sierra imaging workflow and achieved the desired results.

There are alternative methods to capturing the firmware upgrades in the High Sierra installer. But this is not an official Apple-supported workflow, just so that you are aware.

benbass
New Contributor III

@troyewebster Here is what I have. You just need to put the explicit path to your file, and remember that the python script will give you a unique file name on every run. I have my postflight that runs the python script go and rename the file so we can grab it in this EA. We are grabbing the entire line and not doing any parsing at this point. So it's a little messy, but does contain useful information.

Let me know if you have any questions.

#!/bin/bash
########################################
# Script - Extension Attribute
# --Reads the efistatus.log.
########################################
# By Ben Bass
# For ITSD-ISS of JHU-APL
# Dated: 20171005, Last Mod: 20171005
# Version 0.1
#######################################
# This script will read the output from efistatus.log and output the EFI firmware version information.

# send std error to dev null.  Comment out when testing.
exec 2>>/dev/null

# Set variables here
eficheckString="$(grep -A1 'EFI firmware version' "/path/to/your/log/efistatus.log" | tail -1 | cut -f2)"

# Grab the data you want, make sure to check for null returns.
if [[ -z "$eficheckString" ]]; then

    eficheckString="N/A"

fi

# Now echo the results so Casper can grab it.
echo "<result>$eficheckString</result>"

exit 0

Typical EA output:

EFI Version Check: [+] SUCCESS - The EFI Firmware you are running (MBP111.0138.B40) is the expected version for the OS build you have installed (16G29) on your MacBookPro11,1

stevenjklein
Contributor II

@Bruienne: Thanks for the follow-up.

Aaron Weaver, a coworker who knows Python, tweaked it to work as an EA, no interaction needed. Here's a link:

https://gist.github.com/aaronweaver/223ac452ed14ab28b87e96e6ac819929

If the EFI is correct, it returns SUCCESS. Otherwise, it returns ATTENTION.

(Since Jamf already collects OS version and build numbers, we decided to skip reporting that.)

The only problem is that it requires the cacert.pem file in the same directory as the script (or it requires the certifi python module to be installed).

I can push cacert.pem to my Macs, but where do I put it? From what directory are extension attribute scripts executed?

mm2270
Legendary Contributor II

@stevenjklein That's an excellent question. I'm not sure myself, but I would probably just do something like the following.
Deploy both the py script and the cacert into a specific directory on each system, like /Library/Application Support/JAMF/bin/EFiChecker/ and then use an actual EA script like so, which just calls the python script and captures the output to echo back, which, I believe should give you the proper result back in the JSS.

#!/bin/sh

scriptPath="/Library/Application Support/JAMF/bin/EFIChecker/EFIgyLite_cli.py"

Result=$("$scriptPath")

echo "$Result"

In case you're wondering, I purposely left out the <result></result> tags in the final line, because that's already part of the python script's output.
I haven't tested this, but I think as long as it's formatted correctly and surrounded by double quotes, it should work.

Just make sure when packaging it up that the python script retains the executable flag on it or it will fail when the EA tries to run it.

mpenrod
New Contributor III

Is it just me or does this seem like something that JAMF Pro should already be checking? That said, I suppose if Apple wasn't then why would JAMF? It just works! Feature request?

iMatthewCM
New Contributor III

I've actually got a complete workflow for this - it'll deploy the necessary files and make the API call, then send the status back to Jamf Pro for an EA 🙂 Link

mpenrod
New Contributor III

@iMatthewCM Thank you! Hyperlinks in the workflow are not active but a little hunting in your folders and I got it all. Workflow instructions were easy to follow and it is working and my Smart Group is now populated with a ton of systems I need to have upgrade lol.

iMatthewCM
New Contributor III

@mpenrod Glad it worked!

Not sure how to get the links to activate on that root page - if you download the PDF it works well, but yeah, I see that too. Sorry about that, glad you got it sorted out though 🙂

jelockwood
Contributor

Some of the solutions suggested here seem unnecessarily complex in that they require either parsing the EFIgy log file or creating installer packages or other things.

I have detailed my approach here - http://jelockwood.blogspot.com/2018/07/jamf-jss-and-checking-mac-firmware.html

In response to @stevenjklein JSS executes scripts in /private/tmp/<nameofjamfaccount>/

To summarise I use a shell script to populate an extension attribute but in my shell script I use CAT EOF aka heredoc to copy the EFIgyLite_cli.py and cacert.pem files to /tmp on the client Mac. My shell script then runs the python script, uses grep to find the single useful line and uses that as the response to go in to the extension attribute.

I did have to make a small modification to the official EFIgyLite_cli.py script which I have submitted as an enhancement request to the original author.

Duo Labs don't detail it but possible reasons you might get a report saying you are running newer firmware than expected would be if you have downgraded from High Sierra or have run the beta of Mojave or their data being out of date. I have a MacBookPro12,1 reporting newer than expected even though it is running High Sierra 10.13.5, I now recall I used this Mac to install a beta of Mojave on to an external drive.

iMatthewCM
New Contributor III

@jelockwood Glad you found something that works for you 🙂 Your approach is essentially the same as mine, just packaged a little differently. Certainly looks like it'll do the trick!