Munki and configuration profiles

1,714 views
Skip to first unread message

Gregory Neagle

unread,
Dec 16, 2014, 11:24:56 AM12/16/14
to munk...@googlegroups.com
As part of our Yosemite deployment, I'm finally (!) ripping out all the LocalMCX I've been using for years and replacing it all with config profiles.

I've been using a mish-mash of Profile Manager running in a VM and mcxToProfile to generate the profiles.

I have a few older profiles that I had packaged "by hand"; more recently I've been using make_profile_pkg.

But I am unhappy with the the repetitive nature of all this; even with make_profile_pkg there are several things to remember to do, and it seems like a huge pain to manage; especially since I want to keep the actual configuration profiles in Git; having the extra layer/step of having to build new packages all the time is annoying. And all the pkginfo scripting is ugly and repetitive.

So I've been thinking about making Munki treat configuration profiles as another file type it knows how to deal with "natively". Munki currently knows how to install Apple pkgs and how to copy items from dmg files.

I'm proposing extending Munki to be able to do this:

munkiimport /path/to/some/foo.mobileconfig

And Munki will just do the right thing: the profile will be imported into the repo, and Munki will be able to install it or remove it just like it does Firefox or Office2011.

Munki needs to be able to determine if it needs to install the profile: I'm thinking of two mechanisms. The first is to simply use the output of `/usr/bin/profiles -C` (probably with the -o /path/to/file` option to get nice plist output) -- this would give us top-level PayloadIdentifiers -- if the PayloadIdentifier is missing, we need to install (or conversely, if it's there and the profile is now in managed_uninstalls we need to remove it).

This leaves the problem of detecting that the admin has imported a new version of a profile and that we need to re-install. I propose a simple mechanism: The pkginfo for Munki items currently contains an installer_item_hash: the code that installs profiles can record to a simple plist in /Library/Managed Installs a key/value pair -- the key is the top-level PayloadIdentifier; the value is the installer_item_hash. If the hash for the item being considered for install is absent or different, we need to install.

This is not a perfect mechanism: if Munki installs version A of a profile (and records HASH_A for it) and then an admin user manually installs version B of the profile, Munki will not detect this and reinstall version A. Of course, this is not so different from Munki installing Firefox 35 and then an admin user installing Firefox 36...

Before I really dig into this I need to officially release Munki 2.1; this addition (if I go forward with it) probably warrants at least a bump to 2.5.

Feedback appreciated.

-Greg

Daniel Hazelbaker

unread,
Dec 16, 2014, 11:48:43 AM12/16/14
to munk...@googlegroups.com
I've been using a homebrew linux VM for doing MDM & profile management internally here (I found Apple's Profile Manager to be too much of a pain to get it to work properly).  But I would say the potential problem(s) you mentioned would be the same for any MDM / profile management system.  If I tell a computer to install a profile via MDM and then manually go to that machine and install a newer version, the MDM system is going to overwrite it (at some point).

I don't know that I would end up using the munki provided solution as I really like the simplicity of what I have, and it allows me to mark certain settings as a higher priority than others, so they will override the other settings (i.e. the settings in group B would override the settings in group A if the computer is in both groups).  Having said that for system settings, would there be any way to use this along with the "optional installs" (i.e. user choice installs) to manage user-profiles, like e-mail account settings?  I can see this being a good solution to dealing with people needing/wanting to login to somebody else's computer with their network account. They have a new, empty home folder now with no settings for getting to standard services without I.T. helping them get it setup. If I could tell them to launch MSC and install the "Standard User Settings" profile that sets up their e-mail, Calendar, address book, etc. that would be helpful.

It would mean munki would have to track the information you mentioned on a per-user basis, so this may just be outside the scope of what you want to deal with, but just a thought.

Otherwise, as I said, I don't see the potential problems being any different than any other existing system.

Daniel

P.S., I'm in the same boat. As we roll out Yosemite we are also finally getting rid of MCX.

Nick McSpadden

unread,
Dec 16, 2014, 11:51:18 AM12/16/14
to munki-dev
Just to make sure I'm understanding this correctly, the only record of "versioning" taking place is being stored in a plist in /Library/Managed Installs/?  it does means that any mucking around with /Library/Managed Installs/ results in a loss of all current existing versions of stored profiles.  What will Munki do if that plist is missing and it sees a profile to install that is already installed - how will it know at that point which is the "newer" version?

After giving it some thought, I couldn't think of a better solution that didn't involve trying to reinvent receipt versioning in some way.  Unless Munki installs the profile on each run, each time, which could be potentially dangerous depending on the profile.

This also provides no mechanism for user-level profiles, but that's already true with existing tools and this won't change anything.  The best way I've found to do user-level profiles is to install them a local folder and then install a launchagent that installs the profile when the intended account logs in.


--
You received this message because you are subscribed to the Google Groups "munki-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to munki-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
--
Nick McSpadden
Client Systems Manager
Schools of the Sacred Heart, San Francisco

Gregory Neagle

unread,
Dec 16, 2014, 11:56:24 AM12/16/14
to munk...@googlegroups.com
On Dec 16, 2014, at 8:51 AM, Nick McSpadden <nick.mc...@sacredsf.org> wrote:

Just to make sure I'm understanding this correctly, the only record of "versioning" taking place is being stored in a plist in /Library/Managed Installs/?  it does means that any mucking around with /Library/Managed Installs/ results in a loss of all current existing versions of stored profiles.  What will Munki do if that plist is missing and it sees a profile to install that is already installed - how will it know at that point which is the "newer" version?

It would install/reinstall whatever version of the profile it has as "latest"; same as if it was asked to install an Apple pkg and there were no receipt present.


After giving it some thought, I couldn't think of a better solution that didn't involve trying to reinvent receipt versioning in some way.  Unless Munki installs the profile on each run, each time, which could be potentially dangerous depending on the profile.

And slow and resource intensive.


This also provides no mechanism for user-level profiles,

Correct, that is not in scope. Munki currently has no concept of user-level installs anyway.

zack.m...@bsd7.org

unread,
Dec 16, 2014, 12:18:52 PM12/16/14
to munk...@googlegroups.com
If you leave a copy of the Profile in a set location, use the hash for comparison, then compare hashes you can check what the version is. We were using this sty method (real hackjob but it worked) for our Meraki Profile. However the Meraki Profile was no longer verifying and was causing massive issues with OS X 10.10 and our student accounts. Using the hash method would work, not perfect, but it works. 

Gregory Neagle

unread,
Dec 16, 2014, 12:22:20 PM12/16/14
to munk...@googlegroups.com
On Dec 16, 2014, at 9:18 AM, zack.m...@bsd7.org wrote:

If you leave a copy of the Profile in a set location, use the hash for comparison, then compare hashes you can check what the version is.

You would only be comparing Munki's version with the one in the "set location" -- there's no way to verify that that one actually _installed_ is the same one that's in the "set location". Since we can't verify, it suffices to record/keep track of only a hash -- we don't need to keep a copy of the whole profile.

zack.m...@bsd7.org

unread,
Dec 16, 2014, 12:41:30 PM12/16/14
to munk...@googlegroups.com
You can egrep the profiles -P option to see the profiles identifier. If the egrep confirms that the profile with the identifier is installed...which might be a way to store a version number..then you can verify it has been installed. 

The reason we used hash to "re-verify" was because Meraki uses a set identifier of com.meraki.sm.mdm with no version number or anything. If we found the hash of the profile to match the latest version and the profile was already installed, no big deal. If the hash of the copy was old and out of date we would uninstall the profile first, then copy the new one, then re-install. If there was no profile, copy munki latest version, and install. It was just an idea that worked at the time. I would easily say there are better ways, and you are probably going to figure out many better ones. 

This is the script I used to verify that it was installed. I no longer have the full script work that we used as the profile became a nuisance with the issues it was causing.

if /usr/bin/profiles -P | /usr/bin/egrep -q ': com.yourcompany.profile.v1.0.0$' ; then CMDS HERE; else CMDSHERE; fi

Gregory Neagle

unread,
Dec 16, 2014, 12:43:18 PM12/16/14
to munk...@googlegroups.com
On Dec 16, 2014, at 9:41 AM, zack.m...@bsd7.org wrote:

You can egrep the profiles -P option to see the profiles identifier. If the egrep confirms that the profile with the identifier is installed...which might be a way to store a version number..then you can verify it has been installed. 

I have no problem finding profile identifiers. But configuration profiles do not have usable version numbers. We need to store that out-of-band.

A.E. van Bochoven

unread,
Dec 16, 2014, 2:57:08 PM12/16/14
to munk...@googlegroups.com
I've been using a launchdaemon and a script by Håkan Hagenrud whith some modifications to install/uninstall profiles on my fleet for a couple of years now.
Once the launchdaemon and profile-installscript are in place, I set the profiles using 'copy item from dmg' to a designated folder (/Library/Managed Profiles). The launchdaemon and script take care of installing everything that's in this folder (and de-installing everything that's not in there). This probably works the way you are proposing.

Håkan's script has a 'special' option that signals that the profile should not be managed (prefix the profile with '_computerlevel') but I've never used that.

Original script can be found here: https://code.google.com/p/lion-computer-profiles-handler/

-Arjen

bryanzak

unread,
Dec 16, 2014, 3:21:48 PM12/16/14
to munk...@googlegroups.com
I've been sending out profiles via Munki using simple packages built via pkgbuild.

What you propose would reduce some of the repetitiveness of the process. We'd likely adopt it here.

At this point, we only use machine level profiles, so that limitation is not an issue.

As for versioning and detecting what is or isn't installed. I don't see it as much of an issue really. Once you have the ability to deliver profiles via Munki the need to hand install is reduced and the issues you raise aren't much of a concern to me.


Bryan

Erik Gomez

unread,
Dec 16, 2014, 3:36:10 PM12/16/14
to munk...@googlegroups.com
I welcome this change although I ended up writing a script for Tim's tool that largely automate the process of importing into Munki.

I found when moving from MCX to 100% profiles that the majority of the work was in building the profiles and not getting them into Munki. 

Are we going to use the profile creation date ala Tim's tool for versioning or something else?

Sent from my iPhone

Gregory Neagle

unread,
Dec 17, 2014, 1:05:42 AM12/17/14
to munk...@googlegroups.com
Initial implementation is here: https://github.com/munki/munki/tree/config-profile-support

You can munkiimport a configuration profile and/or run makepkginfo on a config profile. Once imported, you can add the name of the item to a manifests' managed_installs or managed_uninstalls (or managed_updates or optional_installs).

Currently only unsigned profiles are supported by munkiimport/makepkginfo. Encrypted profiles should work but are untested.

Install and removal of signed profiles should work, but makepkginfo cannot generate the pkginfo; you'd have to do it manually.

-Greg

Tim Sutton

unread,
Dec 17, 2014, 7:55:25 AM12/17/14
to munk...@googlegroups.com
There's a tiny change I had to make to makepkginfo with profiles I've
generated using mcxToProfile, which apparently have 'Configuration'
for the PayloadType:

- if profile.get('PayloadType') == 'configuration':
+ if profile.get('PayloadType').lower() == 'configuration':

Or perhaps this should just be a strict 'Configuration'. Not sure if
there are tools out there making a PayloadType with a lower-case.

Erik

unread,
Dec 17, 2014, 8:40:35 AM12/17/14
to munk...@googlegroups.com
In case anyone is unsure how to test this out:

Make sure to first read https://github.com/munki/munki/wiki/Building-Munki2-Pkgs (especially if you are using XCode 6.x.x)

In Terminal:

mkdir /Users/Shared/munkibuilds
git clone https://github.com/munki/munki
cd munki
git checkout -b config-profile-support origin/config-profile-support
./code/tools/make_munki_mpkg.sh

With that said, makepkginfo nor munkiimport are correctly reading my .mobileconfigs' metadata.

Gregory Neagle

unread,
Dec 17, 2014, 9:13:59 AM12/17/14
to munk...@googlegroups.com
On Dec 17, 2014, at 5:40 AM, Erik <eriknico...@gmail.com> wrote:

In case anyone is unsure how to test this out:

Make sure to first read https://github.com/munki/munki/wiki/Building-Munki2-Pkgs (especially if you are using XCode 6.x.x)

In Terminal:

mkdir /Users/Shared/munkibuilds
git clone https://github.com/munki/munki
cd munki
git checkout -b config-profile-support origin/config-profile-support
./code/tools/make_munki_mpkg.sh


You can also just run the command-line tools directly from whatever directory you've downloaded them to; no need to build or install:

mkdir /Users/Shared/munkibuilds
cd /Users/Shared/munkibuilds
cd munki
git checkout -b config-profile-support origin/config-profile-support
cd code/client
./munkiimport /path/to/some.mobileconfig
./managedsoftwareupdate

etc. This way you don't disturb your (working) install of Munki tools.

With that said, makepkginfo nor munkiimport are correctly reading my .mobileconfigs' metadata.

Try the latest git push (https://github.com/munki/munki/commit/b61a858f662998355035c684f0415098b93f3eba); Tim Sutton noticed a typo I missed when reorganizing the code last night.

-Greg

Gregory Neagle

unread,
Dec 17, 2014, 9:21:51 AM12/17/14
to munk...@googlegroups.com
It should be just "Configuration", and I've fixed that. I reorganized some code last night and didn't test it afterwards, otherwise I probably would have caught that.

-Greg

Erik

unread,
Dec 17, 2014, 10:25:29 AM12/17/14
to munk...@googlegroups.com
Some of my (working) profiles are giving this error.

Traceback (most recent call last):

  File "/usr/local/munki/makepkginfo", line 1109, in <module>

    main()

  File "/usr/local/munki/makepkginfo", line 1105, in main

    print FoundationPlist.writePlistToString(catinfo)

  File "/usr/local/munki/munkilib/FoundationPlist.py", line 131, in writePlistToString

    raise NSPropertyListSerializationException(error)

munkilib.FoundationPlist.NSPropertyListSerializationException: Property list invalid for format (property lists cannot contain objects of type 'CFNull')

Gregory Neagle

unread,
Dec 17, 2014, 11:13:31 AM12/17/14
to munk...@googlegroups.com
Any chance you could share a profile (here or privately) that triggers such an error? Otherwise I just have to guess what might be causing this.

And right now I don't have any useful guesses.

-Greg

Erik

unread,
Dec 17, 2014, 1:47:08 PM12/17/14
to munk...@googlegroups.com

Childress, Matt

unread,
Dec 17, 2014, 2:51:04 PM12/17/14
to munk...@googlegroups.com

Had another admin bring this situation up and would like some input on ideas to solve it:

     End-users have Admin access on their machines.
     We put Firefox ESR on their machines (named “Firefox.app”).
     End-user might download and install the regular release version of Firefox on their machines.

We want to keep the non-ESR version up-to-date if they decide to do that BUT we don’t want to offer it up for install.  Easy enough to have AutoPkg download both versions, but I’m pretty sure that the non-ESR version will overwrite all of the Firefox ESR as the release typically has a higher version number.

I’m leaning toward renaming the ESR binary “Firefox-ESR.app” which would involve repackaging the DMG (reworking an AutoPkg recipe) and keeping the release version just “Firefox.app” – recalling from several years back how you could keep Firefox version 3 on machines.

Other solutions/ideas?

Thanks!
M@

Gregory Neagle

unread,
Dec 17, 2014, 2:56:47 PM12/17/14
to munk...@googlegroups.com
Support for signed profiles has been added: https://github.com/munki/munki/commit/cb81e4616adbd4288f45d8ee85a8744186aaebe5

-Greg

Samuel Keeley

unread,
Dec 17, 2014, 2:58:54 PM12/17/14
to munk...@googlegroups.com
You don't need to repackage anything.  Just use an array like this:

<key>items_to_copy</key>
  <array>
    <dict>
      <key>destination_item</key>
      <string>Firefox ESR.app</string>
      <key>destination_path</key>
      <string>/Applications</string>
      <key>source_item</key>
      <string>Firefox.app</string>
    </dict>
  </array>

--
You received this message because you are subscribed to the Google Groups "munki-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to munki-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
Samuel Keeley

M@

unread,
Dec 17, 2014, 5:57:47 PM12/17/14
to munk...@googlegroups.com
Sweet!  Thanks so much!  Now to figure out how to do this via an AutoPkg recipe, as I imagine that an recipe override isn't going to give me access to destination_item ...

M@

Gregory Neagle

unread,
Dec 17, 2014, 10:12:01 PM12/17/14
to munk...@googlegroups.com
Two more commits of note:

https://github.com/munki/munki/commit/0e08697252641a9e7f24888a858c9bfb0bc729c9
https://github.com/munki/munki/commit/acc674860acc27c2c4c7c01e96192c9c7dcb3e52

These change what we track in /Library/Managed Installs/ConfigProfileData.plist; instead of just tracking the file hash, we also track the install date as reported by `profiles -C -o ...` immediately after install. On later check, if the recorded install date doesn't match what `profiles -C -o ...` reports, we decide we need to (re)install.

This addresses the scenario where Munki installs some version of a profile, and someone/something else later installs a different version. Munki should now notice this and reinstall the profile. If someone/something else later installs the _same_ version previously installed by Munki, Munki will still reinstall, so this isn't perfect, but it does ensure that the version of the profile that is installed is the one Munki is managing.

-Greg

Josh Malone

unread,
Dec 18, 2014, 10:56:51 AM12/18/14
to munk...@googlegroups.com
You can do that in an override. Just add the items_to_copy key/array
to the end of the pkginfo section in the override:

<key>pkginfo</key>
<dict>
<key>catalogs</key>
<array>
<string>testing</string>
</array>
<key>description</key>
<string>Mozilla Firefox is a free and open source web
browser.</string>
<key>display_name</key>
<string>Mozilla Firefox</string>
<key>name</key>
<string>%NAME%</string>
<key>unattended_install</key>
<true/>
<key>items_to_copy</key>
<array>
<dict>
<key>destination_item</key>
<string>Firefox ESR.app</string>
<key>destination_path</key>
<string>/Applications</string>
<key>source_item</key>
<string>Firefox.app</string>
</dict>
</array>
</dict>

Josh Malone

unread,
Dec 18, 2014, 11:00:05 AM12/18/14
to munk...@googlegroups.com
Urm - well, actually, that override only gets the items_to_copy block;
it leaves the resulting installs array pointing to
/Applications/Firefox.app which is wrong. Not sure how to override the
installs array as well without hard-coding it (which would defeat the
purpose of autopkg).

-Josh

Timothy Sutton

unread,
Dec 18, 2014, 12:05:47 PM12/18/14
to munk...@googlegroups.com
This is getting into autopkg-discuss territory..

But I think that you could add the required additional arguments for makepkginfo to tell it to copy to an alternate location by adding the 'additional_makepkginfo_options' array to your override Input section.


Tim
Reply all
Reply to author
Forward
0 new messages