krypted.com

Tiny Deathstars of Foulness

If you’re in need of MDM in Japanese or German, Jamf Now shipped support for those languages last week. To switch languages, click on your name once logged in, and then click on the language you would like to use.

Enjoy.

May 1st, 2017

Posted In: iPhone, Mac OS X, Mac OS X Server, Mac Security, Mass Deployment

Tags: , , ,

I mentioned mdmclient when I gave the talk on the inner workings of Mobile Device Management, or MDM. There, I spent a lot of time on APNs and profiles, but just kinda’ spoke about mdmclient in terms of it being the agent that runs on macOS to provide mdm parity for the Mac. The mdmclient binary is located at /usr/libexec/mdmclient and provides pretty limited access to see how the Mac reacts to and interprets information coming from a device management provider.

I had been meaning to do a write-up on mdmclient and document what it can do since it first shipped. But as luck would have it, @Mosen on the Slacks beat me to the punch with a fantastic resource at https://mosen.github.io/profiledocs/troubleshooting/mdmclient.html. So here I’d like to focus on just 3 examples of using mdmclient. The first is to see what insight an MDM has to the applications installed (whether that information is actually committed to a database somewhere or not) using QueryInstalledApps:

/usr/libexec/mdmclient QueryInstalledApps

Here, we can see an array output of each bundle installed:

{BundleSize = 27457223;
Identifier = “com.hipchat.HipChat”;
Name = HipChat;
ShortVersion = “3.1.6”;
Version = “3.1.6”;}

Now, we can end up with duplicates, and so focus on just the unique Identifier keys, as follows:

/usr/libexec/mdmclient QueryInstalledApps | grep Identifier | uniq

The second iteration is to see installed profiles. The most basic of these, is to see user profiles, which can be obtained using QueryInstalledProfiles, as follows:

/usr/libexec/mdmclient QueryInstalledProfiles

Now, I could see using the profiles command with the -L option that I have a profile to configure office365 on my machine:

profiles -L

charlesedge[1] attribute: profileIdentifier: com.jamfsw.office365.a5f0e328-ea86-11e3-a26c-6476bab5f328
There are 1 user configuration profiles installed for ‘charlesedge’

So to see what that same information looks like, when queried from an MDM solution:
/usr/libexec/mdmclient QueryInstalledProfiles

QueryInstalledProfiles then returns:

({HasRemovalPasscode = 0;
IsEncrypted = 0;
PayloadContent = (
{PayloadDisplayName = “Charles Edge’s Office 365”;
PayloadIdentifier = “com.jamfsw.office365.a5f0e328-ea86-11e3-a26c-6476bab5f328.exchange.a5f2ccd9-ea86-11e3-b1e0-6476bab5f328”;
PayloadType = “com.apple.ews.account”;
PayloadUUID = “a5f2ccd9-ea86-11e3-b1e0-6476bab5f328”;
PayloadVersion = 1;});
PayloadDescription = “This will configure your Office 365 account for your Mac.”;
PayloadDisplayName = “Charles Edge’s Office 365”;
PayloadIdentifier = “com.jamfsw.office365.a5f0e328-ea86-11e3-a26c-6476bab5f328”;
PayloadOrganization = “JAMF Software”;
PayloadRemovalDisallowed = 0;
PayloadUUID = “a5f0e328-ea86-11e3-a26c-6476bab5f328”;
PayloadVersion = 1;
SignerCertificates = ();})

You can then take action based on this type of information, allow you to either fill a database for agent-based management, or simply take action if something is missing, etc.

QueryInstalledProfiles covers user profiles. To see system, you’ll need installedProfiles:

/usr/libexec/mdmclient installedProfiles | grep "Profile Name"

Run without the grep for a considerably more verbose amount of information.

Finally, let’s look at one more piece of information, which is the hash for the iTunes Store. That’s a point I’ve made a number of times, that the iTunes account email address is never provided to an MDM, once associated to a device or user on a device. Instead, there’s a hash of the account. These are important with VPP, as it allows for reversing (according to the MDM) which users have claimed which apps, or which users are using a given app, as well as how many devices they’re accessing those from. To see a hash, as an MDM sees it:

/usr/libexec/mdmclient QueryAppInstallation | grep iTunesStoreAccountHash

There’s a lot more you can do here, and I’m sure we’ll see a lot more over time. However, the work from @mosen combined with the opening up of the documentation on profiles and the mdm protocol helps to shed some light on how things work under the hood, and how we can use these features to provide greater programatic management for the Mac.

For example, to grab that iTuneshash from earlier, as a Jamf extension attribute you could use the following: https://github.com/krypted/ituneshash/blob/master/ituneshash.sh

April 28th, 2017

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

Tags: , , , , , , ,

Here’s a new extension attribute at https://github.com/krypted/ituneshash/blob/master/ituneshash.sh for grabbing the hash ID used for iTunes Store accounts, useful with VPP:

#!/bin/sh
#
#
#
#Jamf Pro Extension Attribute to return the App Store Account Hash for iTunes
#Note that the return is null if one is not found
#
#
result=`/usr/libexec/mdmclient QueryAppInstallation | grep iTunesStoreAccountHash | sed '/.*\"\(.*\)\".*/ s//\1/g'`
echo "<result>$result</result>"

The output is something like:

<result>oBSmAAAa0nUAAACBHe5AaALlNBg=</result>

Which would bring the string into Jamf Pro

April 26th, 2017

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

Tags: , , , ,

10.12.4 gives us a new option to recheck enrollment via DEP! You can now use the -N flag to recheck a DEP configuration and, if a computer is not enrolled in the correct listing, move the enrollment. This should makes of r an ability to move devices between server, change the URL string in an enrollment profile, and recheck for the removal of an enrollment profile.

To use the option, simply run profiles with the -N option (with elevated privileges):

sudo profiles -N

For the Mac, there are a lot of ways to programmatically handle enrollment, so this is a nice new feature, but not a game changer. But, while not yet available in iOS, if the same functionality could be had with, say, a MDM command, then you would be able to migrate iOS devices between MDMs, provided you already put the data in place so policies ran as expected.

April 18th, 2017

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

There’s a macOS tool called AssetCacheLocatorUtil located at /usr/bin/AssetCacheLocatorUtil. The output is in… stderr. Because stderr is so fun to work with (note that sed -i only works with stdin). So, to update the caching server(s) you are using and only print the IP address of those, you’d do the following:

/usr/bin/AssetCacheLocatorUtil 2>&1 | grep guid | awk '{print$4}' | sed 's/^\(.*\):.*$/\1/' | uniq

If you use Jamf Pro and would like to use this as an extension attribute, that’s posted here: https://github.com/krypted/cachecheck. I didn’t do any of the if/then there, as I’d usually just do that on the JSS.

April 17th, 2017

Posted In: Mac OS X, Mac Security, Mass Deployment, Network Infrastructure, precache

Tags: , , , , , , , , , ,

There are two useful commands when scripting operations that involve filenames and paths. The first of these is dirname: dirname can be used to return the directory portion of a path. The second is basename: basename can be used to output the file name portion of a path.

For our first example, let’s say that we have an output of /users/krypted, which we know to be the original short name of my user. To just see just that username, we could use basename to call it:

basename /users/charlesedge

Basename can also be used to trim output. For example, let’s say there was a document called myresume.pdf in my home folder and we wanted to grab that without the file extension. We could run basename using the -s option, followed by the string at the end that we do not want to see to output of (the file extension:

basename -s .pdf /users/charlesedge/myresume.pdf

The dirname command is even more basic. It outputs the directory portion of the file’s path. For example, based on the same string, the following would tell you what directory the user is in:

dirname /users/charlesedge

A great example of when this gets more useful is keying off of currently active data. For example, if we’re scripting a make operation, we can use the which command to get an output that just contains the path to the make binary:

which make

We can then wrap that for expansion and grab just the place that the active make binary is stored:

dirname `which make`

This allows us to key other operations off the path of an object. A couple of notable example of this is home or homeDirectory paths and then breaking up data coming into a script via a positional parameter (e.g. $1).

You can also use variables as well. Let’s say that

homedir=/users/krypted ; dirname $homedir

Finally, keep in mind that dirname is relative, so if you’re calling it for ~/ then you’ll see the output at that relative path.

April 5th, 2017

Posted In: Mac OS X, Mac OS X Server, Mac Security, Mass Deployment

Tags: , , , ,

The xxd is a bash command in Linux and macOS that is used to take a hexdump (convert a string to hex), or convert hex back to a string. To use xxd, just call it with a couple of options. Below, we’ll use the -p option to export into plain hexdump, and we’ll quote it and the <<< is to take input rather than a file name to convert (the default behavior), as follows:

xxd -p <<< "hey it's a string"

The output would be a hex string, as follows:

6865792069742773206120737472696e670a

Then use the -r option to revert your hex back to text. Since xxd doesn’t allow for a positional parameter to revert, we’ll simply echo the hex string and pipe it back into xxd, as follows:

echo 6865792069742773206120737472696e670a | xxd -r -p

And the output would be (is):

hey it's a string

Other useful options:

  • -b: Perform a binary dump instead of a hex dump
  • -e: what it looks like when a little endian takes a hex dump
  • -h: get help with the command
  • -len: stop after the defined number of characters
  • -u: use uppercase in the hex, instead of the default lower-case (doesn’t seem to actually work on macOS)
  • -v: grab the version of xxd

April 2nd, 2017

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

Tags: , , , , , ,

The videos from the MacADUK sessions are now available on the Internets! Including such great sessions as “What’s New With Managing macOS and iOS” from Marko Jung, “Something something commercial, something something open source” from Graham Gilbert, “Desired State Management Through Automation with Jamf Pro” from John Kitzmiller, “Advanced Mac Software Deployment and Configuration – Just Make it Work” from Tim Sutton, “Securing the Managed Environment – you, me, and everybody” from Pepijn Bruienne, “Munki and Patch. A Comparison” from Ben Toms & James Ridsdale, “Locking down macOS without Locking Up Users (The Sequel)” from Samuel Keeley. Totes fun!

Watch them at https://online-training.amsys.co.uk/courses/macaduk-2017

March 28th, 2017

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

Tags: , , , , ,

March 8th, 2017

Posted In: Mac OS X Server, Mac Security, MacAdmins Podcast

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…

resolv.conf

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

scutil

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}'

networksetup

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[@]}"
do
networksetup -getdnsservers $i
done

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…

dig

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 google.com | grep SERVER:

The output is kinda’ fug:

;; SERVER: 4.2.2.2#53(4.2.2.2)

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

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

nslookup

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 google.com | grep Server: | awk '{print$2}'

system_profiler

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}'

hosts

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

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

ipconfig

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: , , , , , , ,

Next Page »