Tiny Deathstars of Foulness

The next release of iOS (10.3), macOS (10.12.4), and tvOS (10.2) bring us a host of new management features. These include DEP configuration, remote wipe, single app mode, conference room mode, and remote reboot for Apple TVs. The next evolution of iOS brings us sounds in lost mode, the ability to prevent users from connecting to unmanaged wireless networks (just make sure to push that policy after sending down the actual managed wireless networks – or eek), the option to remotely shut down and reboot devices,

The Mac options includes some of the above but also restricting the feature to unlock macOS devices with Touch ID, restrict documents and desktop syncing with Apple’s iCloud service. Shared iPad environments also get new passcode policies.

Jamf Pro 9.98 has also comes with Symantec PKI integration and lots, and lots, and lots of resolutions to product issues. For more, see For a full run-down of profile options and MDM commands:’s_New_in_This_Release.html.

Keeping with Apple’s evolving standards, Managed Preferences and Provisioning Profiles are being deprecated: (which isn’t to say you can’t still deploy these kinds of things using your own scripts, etc).

Finally, if you have a problem in your environment and want to see if it’s been fixed, for a list of defects and product improvements – see

March 23rd, 2017

Posted In: JAMF, Mac OS X, Mac OS X Server

Tags: , , , ,

Leave a Comment

One of my favorite things about grabbing things with scripts is just how many ways (and sometimes how needfully or needlessly convoluted you can make them) to grab the same pieces of information. For example, something as simple as what hosts you use to resolve names on a Mac. There are a number of ways to grab what DNS server a device is using in macOS. So when you’re running a script you might choose to grab DNS information one way or another, according to what you’re after. Some of this might seem more complicated than it should be. And that’s correct…


The /etc/resolv.conf file is updated automatically to look at what servers are used to resolve names used for DNS. The easiest way to see theses to simply cat it and grep for nameserver:

cat /etc/resolv.conf | grep nameserver


The next way we’ll grab DNS information is using scutil. Here, we use the –dns option, which outputs a lot of DNS stuffs, including all the built-in resolvers:

scutil --dns

To just grab the name servers:

scutil --dns | grep nameserver

We can also simplify the output to just the servers with awk:

scutil --dns | grep nameserver | awk '{print$3}'


The second way is using networksetup. This command has an option to get a DNS server in (shocker) -getdnsservers. However, you have to list the interface for each. So below we’ll dump all interfaces into an array using -listallhardwareports and then read them in using a for loop and querying the name servers.

interfaces=( "$(networksetup -listallhardwareports | grep Hardware | cut -c 16-900)" )
for i in "${interfaces[@]}"
networksetup -getdnsservers $i

The one tricky thing in this one is I initially forgot to quote the interfaces as they went into the array, which meant each word of the interface was an item in the array and therefore the -getdnsservers option failed. Once I quoted, it was all happy. The other thing I can point out is I used cut instead of sed because it was easier to quote; however, it seems unlikely the name can be more than 890 characters, so I think it’s fine…


You can also use dig. Here, you’ll query for a name without using an @ option, but omit everything but the line with the server that responded:

dig | grep SERVER:

The output is kinda’ fug:


For simpler output, we’ll use sed to constrain the output to just what’s between the parenthesis:

dig | grep SERVER: | sed 's/^.*(//;s/)$//'


nslookup is a tool similar to dig, used for querying names. We’ll basically do the same thing as above, just using awk as it’s just a standard position in a line:

nslookup | grep Server: | awk '{print$2}'


Then there’s system_profiler, the command line interface for System Profiler. Here, we can query the SPNetworkDataType. This is going to produce a lot of output, so we can limit it to just the DNS servers using grep to constrain to just the lines we want and awk for just the columns in those lines, as follows:

system_profiler SPNetworkDataType | grep "Domain Name Servers:" | awk '{print$4}'


@knapjack added to use hosts. I had to use verbose mode to pull the local name server as follows:

host -v -t ns | grep Received | awk '{print $5}'


Thanks to the lovely Allister (@sacrilicious), we also have ipconfig to add to the list:

/usr/sbin/ipconfig getpacket en0 2> /dev/null | grep name_ | cut -d' ' -f3-

There are tons of ways to find things in macOS. Do you have a way to find a DNS server that I didn’t think of here?

March 6th, 2017

Posted In: bash, Mac OS X, Mac OS X Server, Mac Security, Ubuntu

Tags: , , , , , , ,


I’ve written about SQLite databases here and there over the years. A number of Apple tools and third party tools for the platform run on SQLite and it’s usually a pretty straight forward process to get into a database and inspect what’s there and how you might programmatically interact with tools that store data in SQLite. And I’ll frequently use a tool like Navicat to quickly and visually hop in and look at what happens when I edit data that then gets committed to the database.

But I don’t always have tools like that around. So when I want to inspect new databases, or at least those new to me, I need to use the sqlite3 command. First, I need to find the databases, which are .db files, usually stored somewhere that a user has rights to alter the file. For example,  /Library/Application Support/My Product. In that folder, you’ll usually find a db file, which for this process, we’ll use the example of Data.db.

To access that file, you’d simply run sqlite3 with the path of the database, as follows:

sqlite3 /Library/Application\ Support/My\ Product/Data.db

To see a list of tables in the database, use .tables (note that a tool like Postgress would use commands like /tr but in SQLite we can run commands with a . in front and statements like select do not use those):


To then see a list of columns, use .schema followed by the name of a table. In this case, we’ll look at iOS_devices, which tracks the basic devices stored on the server:

.schema iOS_devices

The output shows us a limited set of fields, meaning that the UDID is used to link information from other tables to the device. I like to enable column headers, unless actually doing an export (and then I usually do it as well):

.headers ON

Then, you can run a standard select to see what is in each field, which in the below example would be listing all information from all rows in the myapptable table:

select * from myapptable;

The output might be as follows:

abcdefg|2017-01-26T17:02:39Z|Contents of field 3|Contents of field four

Another thing to consider is that a number of apps will use multiple .db files. For example, one might contain tables about users, another for groups, and another for devices in a simple asset tracking system. This doesn’t seem great at first, but I’ve never really judged it, as I don’t know what kind of design considerations they were planning for that I don’t know. If so, finding that key (likely GUID in the above example) will likely be required if you’re doing this type of reverse engineer to find a way to programmatically inject information into or extract information out of a tool that doesn’t otherwise allow you to do so.

February 24th, 2017

Posted In: Mac OS X, SQL

Tags: , , , , , , , , ,

February 23rd, 2017

Posted In: MacAdmins Podcast

Tags: , , ,

My latest piece is up. This one focuses on perfecting your sales pitch. It starts as follows:

It’s hard to make a sale if you have a lousy sales pitch. Delivering fresh pitches that allow your product or service to stand out from the others is job number one in sales.

So how do you incite interest rather than yawns? Here are six simple tips.

You can find the rest of the article here:

February 16th, 2017

Posted In: Articles and Books

Tags: , , , ,

So I comment a lot of lines out in my /etc/hosts file. This usually means that I end up with a lot of cruft at the top of my file. And while I write comments into files and scripts here and there, I don’t always want to see them. So I can grep them out by piping the output of the file to grep as follows:

cat /etc/hosts | grep -v "^#"

You could also do the same, eliminating all lines that start with a “v” instead:

cat !$ | grep -v "^v"

February 13th, 2017

Posted In: Mac OS X, Unix

Tags: , , , , , ,

February 10th, 2017

Posted In: MacAdmins Podcast

Tags: , , ,

When you’re regression testing, you frequently just don’t want any delays for scripts unless you intentionally sleep your scripts. By default Safari has an internal delay that I’d totally forgotten about. So if your GUI scripts (yes, I know, yuck) are taking too long to run, check this out and see if it helps:

defaults write WebKitInitialTimedLayoutDelay 0

With a script I was recently working on, this made the thing take about an hour less. Might help for your stuffs, might not.

If not, to undo:

defaults delete WebKitInitialTimedLayoutDelay


February 1st, 2017

Posted In: Mac OS X Server, Mac Security

Tags: , , , , , , , ,

Built a quick extension attribute for Jamf Pro environments to check if TouchID is enabled and report back a string in $result – this could easily be modified and so I commented a few pointers for environments that might need to modify it (e.g. to check for user-level as it’s currently system-level). To see/have the code, check

January 18th, 2017

Posted In: JAMF, Mac Security

Tags: , , , , , , ,

The codesign command is used to sign apps and check the signature of apps. Apps need to be signed more and more and more these days. So, you might need to loop through your apps and verify that they’re signed. You might also choose to stop trusting given signing authorities if one is compromised. To check signing authorities, you can use

codesign -dv --verbose=4 /Applications/ 2>&1 | sed -n '/Authority/p'

The options in the above command:

  • -d is used to display information about the app (as opposed to a -s which would actually sign the app)
  • -v increases the verbosity level (without the v’s we won’t see the signing “Authority”)
  • –verbose=4 indicates the level of verbosity
  • 2>&1 redirects stderr to stdout
  • /Applications/ – the path to the app we’re checking (or signing if you’re signing)

Then we pipe the output into a simple sed and get the signing chain. Or don’t. For example, if you’re scripting don’t forget a sanity check for whether an object isn’t signed. For example, if we just run the following for a non-signed app:

codesign -dv --verbose=4 /Applications/Utilities/

The output would be as follows:

/Applications/Utilities/ code object is not signed at all

January 12th, 2017

Posted In: Apps, Mac OS X, Mac OS X Server

Tags: , , , , , , ,

Next Page »