From daf09a85fa0d10414ec384edffd673fe96ca8028 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Fri, 12 Dec 2014 09:55:24 -0800 Subject: [PATCH 01/31] Update profiles.rb add 10.10 --- lib/facter/profiles.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index bda98be..fec47f7 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -1,6 +1,6 @@ Facter.add(:profiles) do confine :kernel => "Darwin" - confine :macosx_productversion_major => %w{10.7 10.8 10.9} + confine :macosx_productversion_major => %w{10.7 10.8 10.9 10.10} setcode do profiles = %x{/usr/bin/profiles -P | /usr/bin/grep profileIdentifier | awk '{ print $4 }'}.split("\n") profiles.join(',') From 9379685cad1a1f1ce27957dfe1785306141a59bd Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Fri, 12 Dec 2014 10:07:43 -0800 Subject: [PATCH 02/31] Delete metadata.json this breaks R10k and is no longer needed --- metadata.json | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 metadata.json diff --git a/metadata.json b/metadata.json deleted file mode 100644 index d102bd8..0000000 --- a/metadata.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "requirements": [ - { "name": "pe", "version_requirement": "3.x" }, - { "name": "puppet", "version_requirement": "3.x" } - ], - "operatingsystem_support": [ - { - "operatingsystem": "Darwin" - } - ] -} From d5e77e79e2031602971a94b1a23bc84a5e2b3dc7 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 8 Jun 2015 18:26:19 -0500 Subject: [PATCH 03/31] add 10.11 --- lib/facter/profiles.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index fec47f7..bccf008 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -1,6 +1,6 @@ Facter.add(:profiles) do confine :kernel => "Darwin" - confine :macosx_productversion_major => %w{10.7 10.8 10.9 10.10} + confine :macosx_productversion_major => %w{10.7 10.8 10.9 10.10 10.11} setcode do profiles = %x{/usr/bin/profiles -P | /usr/bin/grep profileIdentifier | awk '{ print $4 }'}.split("\n") profiles.join(',') From b898b15e140f791a5cabfe251e84652933c11144 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Wed, 12 Aug 2015 21:57:18 -0700 Subject: [PATCH 04/31] lint --- .gitignore | 1 + examples/init.pp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index ec414a8..d9cd236 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.swp pkg +.DS_Store diff --git a/examples/init.pp b/examples/init.pp index 2ca937d..5f96855 100644 --- a/examples/init.pp +++ b/examples/init.pp @@ -1,4 +1,4 @@ mac_profiles_handler::manage { 'com.puppetlabs.myprofile': - ensure => present, + ensure => present, file_source => 'puppet:///modules/mymodule/com.puppetlabs.myprofile.mobileconfig', } From b8ad950252bc80767405ef3fbc99a11f87a72825 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Thu, 3 Dec 2015 13:08:04 -0800 Subject: [PATCH 05/31] Updated to work with clean install of Puppet 4 by using the puppet_vardir variable instead of a hardcoded path --- manifests/manage.pp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/manifests/manage.pp b/manifests/manage.pp index 0cd1044..77ca78c 100644 --- a/manifests/manage.pp +++ b/manifests/manage.pp @@ -15,20 +15,20 @@ mode => '0700', } - if ! defined(File['/var/lib/puppet/mobileconfigs']) { - file { '/var/lib/puppet/mobileconfigs': + if ! defined(File["${::puppet_vardir}/mobileconfigs"]) { + file { "${::puppet_vardir}/mobileconfigs": ensure => directory, } } case $type { 'template': { - file { "/var/lib/puppet/mobileconfigs/${name}": + file { "${::puppet_vardir}/mobileconfigs/${name}": ensure => file, content => $file_source, } } default: { - file { "/var/lib/puppet/mobileconfigs/${name}": + file { "${::puppet_vardir}/mobileconfigs/${name}": ensure => file, source => $file_source, } @@ -37,7 +37,7 @@ if $ensure=='present'{ exec { "remove-profile-${name}": - subscribe => File["/var/lib/puppet/mobileconfigs/${name}"], + subscribe => File["${::puppet_vardir}/mobileconfigs/${name}"], before => Profile_manager[$name], refreshonly => true, command => "/usr/bin/profiles -R -p ${name}", @@ -47,8 +47,8 @@ profile_manager { $name: ensure => $ensure, - profile => "/var/lib/puppet/mobileconfigs/${name}", - require => File["/var/lib/puppet/mobileconfigs/${name}"], + profile => "${::puppet_vardir}/mobileconfigs/${name}", + require => File["${::puppet_vardir}/mobileconfigs/${name}"], } From 5c66a673cd79d0400848662dcbcade583fc263d0 Mon Sep 17 00:00:00 2001 From: JDHatman Date: Thu, 19 Feb 2015 12:33:32 -0600 Subject: [PATCH 06/31] prevent false positives Changed the def exists? to better guard against false positives. It will grab an exact match for the profile name instead of grabbing similar profile names that may not be correct. --- lib/puppet/provider/profile_manager/osx.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/puppet/provider/profile_manager/osx.rb b/lib/puppet/provider/profile_manager/osx.rb index 41481d7..df78a23 100644 --- a/lib/puppet/provider/profile_manager/osx.rb +++ b/lib/puppet/provider/profile_manager/osx.rb @@ -16,7 +16,7 @@ def destroy end def exists? - `/usr/bin/profiles -P | /usr/bin/grep '#{resource[:name]}'` + `/usr/bin/profiles -P | /usr/bin/awk '{ print $4 }' | /usr/bin/grep -x '#{resource[:name]}'` if $? == 0 return true else From 445d7b75773524f868f9512164447dd5c6f056cb Mon Sep 17 00:00:00 2001 From: Graham Gilbert Date: Wed, 30 Mar 2016 11:47:30 +0100 Subject: [PATCH 07/31] Add in dependency for puppetlabs/stdlib --- Modulefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modulefile b/Modulefile index e49d4f2..729944c 100644 --- a/Modulefile +++ b/Modulefile @@ -8,4 +8,4 @@ description 'This module provides two resource types for managing configuration project_page 'https://github.com/ryanycoleman/rcoleman-mac_profiles_handler' ## Add dependencies, if any: -# dependency 'username/name', '>= 1.2.0' +dependency 'puppetlabs/stdlib', '>= 2.3.1' From c32e1337e242877b83d6860e4670d2a72e781a99 Mon Sep 17 00:00:00 2001 From: Graham Gilbert Date: Wed, 30 Mar 2016 11:49:21 +0100 Subject: [PATCH 08/31] Document the requirement in the readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 25ffdf0..f43e81b 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ mac_profiles_handler::manage { 'com.puppetlabs.myprofile': You must pass the profilers identifier as your namevar, ensure accepts present or absent and file_source behaves the same way source behaves for file. +## Dependencies + +* [puppetlabs/stdlib >= 2.3.1](https://forge.puppetlabs.com/puppetlabs/stdlib) + ## To-Do Improve provider parsing. Handle more types of configuration profiles. From 25efd34392c86e4342e5f35b923f38548920e000 Mon Sep 17 00:00:00 2001 From: Victor Vrantchan Date: Sun, 31 Jul 2016 15:20:56 -0400 Subject: [PATCH 09/31] add 10.12 --- lib/facter/profiles.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index bccf008..15882ae 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -1,6 +1,6 @@ Facter.add(:profiles) do confine :kernel => "Darwin" - confine :macosx_productversion_major => %w{10.7 10.8 10.9 10.10 10.11} + confine :macosx_productversion_major => %w{10.7 10.8 10.9 10.10 10.11 10.12} setcode do profiles = %x{/usr/bin/profiles -P | /usr/bin/grep profileIdentifier | awk '{ print $4 }'}.split("\n") profiles.join(',') From c73fa42a172b43aca60f304255e0c69b7886498e Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 1 Aug 2016 08:55:32 -0500 Subject: [PATCH 10/31] full path to awk --- lib/facter/profiles.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 15882ae..8612a93 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -2,7 +2,7 @@ confine :kernel => "Darwin" confine :macosx_productversion_major => %w{10.7 10.8 10.9 10.10 10.11 10.12} setcode do - profiles = %x{/usr/bin/profiles -P | /usr/bin/grep profileIdentifier | awk '{ print $4 }'}.split("\n") + profiles = %x{/usr/bin/profiles -P | /usr/bin/grep profileIdentifier | /usr/bin/awk '{ print $4 }'}.split("\n") profiles.join(',') end end From be33be46233fc818a30573efea8646f34e97a5f3 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 1 Aug 2016 09:09:50 -0500 Subject: [PATCH 11/31] we did not really need to grep and awk --- lib/facter/profiles.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 8612a93..c0f26d9 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -2,7 +2,16 @@ confine :kernel => "Darwin" confine :macosx_productversion_major => %w{10.7 10.8 10.9 10.10 10.11 10.12} setcode do - profiles = %x{/usr/bin/profiles -P | /usr/bin/grep profileIdentifier | /usr/bin/awk '{ print $4 }'}.split("\n") - profiles.join(',') + profiles = [] + + output = %x{/usr/bin/profiles -P} + + output.each_line do |line| + if line.include? 'profileIdentifier' + profiles << line.split(' ')[3] + end + end + + profiles.join(',') end end From 9393e5d9bb4eb4f04e8a0e5715bce02d85d163a5 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 1 Aug 2016 10:04:08 -0500 Subject: [PATCH 12/31] output a list instead of comma seperated values --- lib/facter/profiles.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index c0f26d9..1d2d59d 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -12,6 +12,7 @@ end end - profiles.join(',') + profiles + end end From 8764cd34a62a6c576bfc3fb642d1f917ac5b6b15 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 1 Aug 2016 10:06:29 -0500 Subject: [PATCH 13/31] Confine in a different way so it doesn't have to update every year --- lib/facter/profiles.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 1d2d59d..1111f78 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -1,14 +1,15 @@ Facter.add(:profiles) do - confine :kernel => "Darwin" - confine :macosx_productversion_major => %w{10.7 10.8 10.9 10.10 10.11 10.12} + confine :kernel => 'Darwin' setcode do profiles = [] - output = %x{/usr/bin/profiles -P} + if Facter.value(:os)['release']['major'].to_i >= 12 + output = %x{/usr/bin/profiles -P} - output.each_line do |line| - if line.include? 'profileIdentifier' - profiles << line.split(' ')[3] + output.each_line do |line| + if line.include? 'profileIdentifier' + profiles << line.split(' ')[3] + end end end From a04f5cbd752f007231ae99a251b0e5aaccc4dc11 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 1 Aug 2016 10:25:34 -0500 Subject: [PATCH 14/31] use the fact, save the time --- lib/puppet/provider/profile_manager/osx.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/puppet/provider/profile_manager/osx.rb b/lib/puppet/provider/profile_manager/osx.rb index df78a23..1bf1e96 100644 --- a/lib/puppet/provider/profile_manager/osx.rb +++ b/lib/puppet/provider/profile_manager/osx.rb @@ -5,19 +5,18 @@ defaultfor :operatingsystem => :darwin - commands :profiles => "/usr/bin/profiles" + commands :profilescmd => '/usr/bin/profiles' def create - profiles('-I', '-F', resource[:profile]) + profilescmd('-I', '-F', resource[:profile]) end def destroy - profiles('-R', '-p', resource[:name]) + profilescmd('-R', '-p', resource[:name]) end def exists? - `/usr/bin/profiles -P | /usr/bin/awk '{ print $4 }' | /usr/bin/grep -x '#{resource[:name]}'` - if $? == 0 + if Facter.value(:profiles).include? resource[:name] return true else return false From 04901df22ef7c75552f1d0fb4ed0088578bd245c Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 8 Aug 2016 14:10:56 -0500 Subject: [PATCH 15/31] Use `Facter::Util::Resolution.exec` --- lib/facter/profiles.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 1111f78..2ae04fa 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -4,7 +4,7 @@ profiles = [] if Facter.value(:os)['release']['major'].to_i >= 12 - output = %x{/usr/bin/profiles -P} + output = Facter::Util::Resolution.exec('/usr/bin/profiles -P') output.each_line do |line| if line.include? 'profileIdentifier' From 610ee52726807b9ce63dc5c53b0ceba653fb9668 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 8 Aug 2016 14:14:57 -0500 Subject: [PATCH 16/31] simplify exists function --- lib/puppet/provider/profile_manager/osx.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/puppet/provider/profile_manager/osx.rb b/lib/puppet/provider/profile_manager/osx.rb index 1bf1e96..546303b 100644 --- a/lib/puppet/provider/profile_manager/osx.rb +++ b/lib/puppet/provider/profile_manager/osx.rb @@ -16,10 +16,6 @@ def destroy end def exists? - if Facter.value(:profiles).include? resource[:name] - return true - else - return false - end + return Facter.value(:profiles).include? resource[:name] end end From d448baef2c55ddf6fcc0e4b6ef75a4c3040f7040 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 8 Aug 2016 15:05:11 -0500 Subject: [PATCH 17/31] Use system profiler and get more information --- lib/facter/profiles.rb | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 2ae04fa..2cd994b 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -1,15 +1,24 @@ +require 'puppet/util/plist' +require 'time' + Facter.add(:profiles) do confine :kernel => 'Darwin' setcode do - profiles = [] + profiles = {} if Facter.value(:os)['release']['major'].to_i >= 12 - output = Facter::Util::Resolution.exec('/usr/bin/profiles -P') - output.each_line do |line| - if line.include? 'profileIdentifier' - profiles << line.split(' ')[3] - end + output = Facter::Util::Resolution.exec('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') + + for item in Puppet::Util::Plist.parse_plist(output)[0]['_items'][0]['_items'] + profiles[item['spconfigprofile_profile_identifier']] = { + 'name' => item['_name'], + 'description' => item['spconfigprofile_description'], + 'verification_state' => item['spconfigprofile_verification_state'], + 'uuid' => item['spconfigprofile_profile_uuid'], + 'organization' => item['spconfigprofile_organization'], + 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first), + } end end From e886e108741d6075f8ad8f954428a15d2caeced0 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 8 Aug 2016 15:08:09 -0500 Subject: [PATCH 18/31] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f43e81b..29c78dd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This module provides two resource types for interacting with OS X configuration The profile_manager resource type is the back-end type that interacts with /usr/bin/profiles for creating, destroying and verifying a resource type. The mac_profiles_handler::manage resource type is user-facing and handles the management of the actual files. -A basic fact is also provided to list installed profiles. +A structured fact is also provided to list installed profiles along with some metadata. ## Usage @@ -31,11 +31,11 @@ You must pass the profilers identifier as your namevar, ensure accepts present o ## Dependencies * [puppetlabs/stdlib >= 2.3.1](https://forge.puppetlabs.com/puppetlabs/stdlib) +* Puppet >= 4.4.0 for `puppet/util/plist`, for earlier versions use d13469a. ## To-Do Improve provider parsing. Handle more types of configuration profiles. -The fact should create a fact for each profile, bonus points for using system_profiler. Improve documentation when author isn't presenting the next morning. ## Contributing From 44759ce18fb5ac2a18036cfb636677445c9d8497 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 8 Aug 2016 21:43:24 -0500 Subject: [PATCH 19/31] add payload information --- lib/facter/profiles.rb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 2cd994b..3e5c477 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -12,13 +12,26 @@ for item in Puppet::Util::Plist.parse_plist(output)[0]['_items'][0]['_items'] profiles[item['spconfigprofile_profile_identifier']] = { - 'name' => item['_name'], + 'display_name' => item['_name'], 'description' => item['spconfigprofile_description'], 'verification_state' => item['spconfigprofile_verification_state'], 'uuid' => item['spconfigprofile_profile_uuid'], 'organization' => item['spconfigprofile_organization'], 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first), + 'payload' => [], } + + for pl in item['_items'] + profiles[item['spconfigprofile_profile_identifier']]['payload'] << { + 'name' => pl['_name'], + 'display_name' => pl['spconfigprofile_payload_display_name'], + 'identifier' => pl['spconfigprofile_payload_identifier'], + 'uuid' => pl['spconfigprofile_payload_uuid'], + # commented out because this is returned in old ASCII plist format + # which cfpropertylist cannot handle, so the data is useless. + #'data' => pl['spconfigprofile_payload_data'], + } + end end end From 28848deb421caa60dacaa97a220fd3c97972b272 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Tue, 9 Aug 2016 10:22:16 -0500 Subject: [PATCH 20/31] Keep receipts to better determine install status If profiles are changed outside of Puppet, we previously would not know. With this change, we keep track of the install time of profiles immediately after installation and compare that to what Facter gives us. --- lib/puppet/provider/profile_manager/osx.rb | 60 +++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/lib/puppet/provider/profile_manager/osx.rb b/lib/puppet/provider/profile_manager/osx.rb index 546303b..597d950 100644 --- a/lib/puppet/provider/profile_manager/osx.rb +++ b/lib/puppet/provider/profile_manager/osx.rb @@ -1,3 +1,5 @@ +require 'puppet/util/plist' + Puppet::Type.type(:profile_manager).provide :osx do desc "Provides management of mobileconfig profiles on OS X." @@ -9,6 +11,7 @@ def create profilescmd('-I', '-F', resource[:profile]) + writereceipt() end def destroy @@ -16,6 +19,61 @@ def destroy end def exists? - return Facter.value(:profiles).include? resource[:name] + return installed() + end + + def installed + # if already installed, check if it is the right one. + # if not installed, return false. + if Facter.value(:profiles).include? resource[:name] + return current() + else + return false + end + end + + def getinstalleddate + + # must be rerun as the output from Facter's earlier run is now + # outdated, but this only runs on refresh so not horrible. + output = Puppet::Util::Execution.execute('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') + + for item in Puppet::Util::Plist.parse_plist(output)[0]['_items'][0]['_items'] + if item['spconfigprofile_profile_identifier'] == resource[:name] + return DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first) + end + end + + end + + def getreceipts + begin + receipts = Puppet::Util::Plist.read_plist_file(Facter.value(:puppet_vardir) + '/mobileconfigs/receipts.plist') + rescue IOError, Errno::ENOENT + receipts = {} + end + + return receipts end + + def writereceipt + # get install time from profile, write to disk so we know if the + # currently installed profile is the one we installed, this uses + # code from the fact but needs to re-run immediately. + receipts = getreceipts() + + receipts[resource[:name]] = {'install_date'=> getinstalleddate()} + + Puppet::Util::Plist.write_plist_file(receipts, Facter.value(:puppet_vardir) + '/mobileconfigs/receipts.plist') + end + + def current + begin + return getinstalleddate().to_time == getreceipts()[resource[:name]]['install_date'] + rescue NoMethodError + # no matching receipt + return false + end + end + end From fe2f006cfd495e7adc5bb698d43352ce93f6baf0 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Tue, 9 Aug 2016 11:05:12 -0500 Subject: [PATCH 21/31] Refreshable provider Previously this was removing the profile and then installing the new one, this adds refresh support so profiles which may break things when removed (802.1x, certificates, etc) won't briefly disappear. --- lib/puppet/type/profile_manager.rb | 4 ++++ manifests/manage.pp | 17 ++++------------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/lib/puppet/type/profile_manager.rb b/lib/puppet/type/profile_manager.rb index 54938b5..442b6e5 100644 --- a/lib/puppet/type/profile_manager.rb +++ b/lib/puppet/type/profile_manager.rb @@ -18,6 +18,10 @@ ensurable + def refresh + provider.create + end + newparam(:name, :namevar => true) newparam(:profile) end diff --git a/manifests/manage.pp b/manifests/manage.pp index 77ca78c..2b7e3af 100644 --- a/manifests/manage.pp +++ b/manifests/manage.pp @@ -35,20 +35,11 @@ } } - if $ensure=='present'{ - exec { "remove-profile-${name}": - subscribe => File["${::puppet_vardir}/mobileconfigs/${name}"], - before => Profile_manager[$name], - refreshonly => true, - command => "/usr/bin/profiles -R -p ${name}", - onlyif => "/usr/bin/profiles -P | /usr/bin/grep -q ${name}", - } - } - profile_manager { $name: - ensure => $ensure, - profile => "${::puppet_vardir}/mobileconfigs/${name}", - require => File["${::puppet_vardir}/mobileconfigs/${name}"], + ensure => $ensure, + profile => "${::puppet_vardir}/mobileconfigs/${name}", + require => File["${::puppet_vardir}/mobileconfigs/${name}"], + subscribe => File["${::puppet_vardir}/mobileconfigs/${name}"], } From c06e46c884dbe319d851666f0b9745b5ae4ddff1 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Thu, 11 Aug 2016 16:04:09 -0700 Subject: [PATCH 22/31] mega cleanup --- lib/facter/profiles.rb | 57 +++++++++++----------- lib/puppet/provider/profile_manager/osx.rb | 33 ++++++------- lib/puppet/type/profile_manager.rb | 3 +- 3 files changed, 43 insertions(+), 50 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 3e5c477..052085c 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -2,40 +2,39 @@ require 'time' Facter.add(:profiles) do - confine :kernel => 'Darwin' + confine kernel: 'Darwin' setcode do - profiles = {} + profiles = {} - if Facter.value(:os)['release']['major'].to_i >= 12 + if Facter.value(:os)['release']['major'].to_i >= 12 - output = Facter::Util::Resolution.exec('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') + output = Facter::Util::Resolution.exec('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') - for item in Puppet::Util::Plist.parse_plist(output)[0]['_items'][0]['_items'] - profiles[item['spconfigprofile_profile_identifier']] = { - 'display_name' => item['_name'], - 'description' => item['spconfigprofile_description'], - 'verification_state' => item['spconfigprofile_verification_state'], - 'uuid' => item['spconfigprofile_profile_uuid'], - 'organization' => item['spconfigprofile_organization'], - 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first), - 'payload' => [], - } + for item in Puppet::Util::Plist.parse_plist(output)[0]['_items'][0]['_items'] + profiles[item['spconfigprofile_profile_identifier']] = { + 'display_name' => item['_name'], + 'description' => item['spconfigprofile_description'], + 'verification_state' => item['spconfigprofile_verification_state'], + 'uuid' => item['spconfigprofile_profile_uuid'], + 'organization' => item['spconfigprofile_organization'], + 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first), + 'payload' => [] + } - for pl in item['_items'] - profiles[item['spconfigprofile_profile_identifier']]['payload'] << { - 'name' => pl['_name'], - 'display_name' => pl['spconfigprofile_payload_display_name'], - 'identifier' => pl['spconfigprofile_payload_identifier'], - 'uuid' => pl['spconfigprofile_payload_uuid'], - # commented out because this is returned in old ASCII plist format - # which cfpropertylist cannot handle, so the data is useless. - #'data' => pl['spconfigprofile_payload_data'], - } - end - end - end - - profiles + for pl in item['_items'] + profiles[item['spconfigprofile_profile_identifier']]['payload'] << { + 'name' => pl['_name'], + 'display_name' => pl['spconfigprofile_payload_display_name'], + 'identifier' => pl['spconfigprofile_payload_identifier'], + 'uuid' => pl['spconfigprofile_payload_uuid'], + # commented out because this is returned in old ASCII plist format + # which cfpropertylist cannot handle, so the data is useless. + # 'data' => pl['spconfigprofile_payload_data'], + } + end + end + end + profiles end end diff --git a/lib/puppet/provider/profile_manager/osx.rb b/lib/puppet/provider/profile_manager/osx.rb index 597d950..c5a075c 100644 --- a/lib/puppet/provider/profile_manager/osx.rb +++ b/lib/puppet/provider/profile_manager/osx.rb @@ -1,17 +1,17 @@ require 'puppet/util/plist' Puppet::Type.type(:profile_manager).provide :osx do - desc "Provides management of mobileconfig profiles on OS X." + desc 'Provides management of mobileconfig profiles on OS X.' - confine :operatingsystem => :darwin + confine operatingsystem: :darwin - defaultfor :operatingsystem => :darwin + defaultfor operatingsystem: :darwin - commands :profilescmd => '/usr/bin/profiles' + commands profilescmd: '/usr/bin/profiles' def create profilescmd('-I', '-F', resource[:profile]) - writereceipt() + writereceipt end def destroy @@ -19,21 +19,20 @@ def destroy end def exists? - return installed() + installed end def installed # if already installed, check if it is the right one. # if not installed, return false. if Facter.value(:profiles).include? resource[:name] - return current() + return current else return false end end def getinstalleddate - # must be rerun as the output from Facter's earlier run is now # outdated, but this only runs on refresh so not horrible. output = Puppet::Util::Execution.execute('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') @@ -43,7 +42,6 @@ def getinstalleddate return DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first) end end - end def getreceipts @@ -53,27 +51,24 @@ def getreceipts receipts = {} end - return receipts + receipts end def writereceipt # get install time from profile, write to disk so we know if the # currently installed profile is the one we installed, this uses # code from the fact but needs to re-run immediately. - receipts = getreceipts() + receipts = getreceipts - receipts[resource[:name]] = {'install_date'=> getinstalleddate()} + receipts[resource[:name]] = { 'install_date' => getinstalleddate } Puppet::Util::Plist.write_plist_file(receipts, Facter.value(:puppet_vardir) + '/mobileconfigs/receipts.plist') end def current - begin - return getinstalleddate().to_time == getreceipts()[resource[:name]]['install_date'] - rescue NoMethodError - # no matching receipt - return false - end + return getinstalleddate.to_time == getreceipts[resource[:name]]['install_date'] + rescue NoMethodError + # no matching receipt + return false end - end diff --git a/lib/puppet/type/profile_manager.rb b/lib/puppet/type/profile_manager.rb index 442b6e5..9d0e23b 100644 --- a/lib/puppet/type/profile_manager.rb +++ b/lib/puppet/type/profile_manager.rb @@ -1,5 +1,4 @@ Puppet::Type.newtype(:profile_manager) do - @doc = <<-EOT Manage Apple Configuration Profiles http://help.apple.com/profilemanager/mac/10.7/#apd88330954-6FA0-4568-A88E-7F6828E763A7 @@ -22,6 +21,6 @@ def refresh provider.create end - newparam(:name, :namevar => true) + newparam(:name, namevar: true) newparam(:profile) end From 0673f84c4816c8de98a8b715c49fee59ce8e697b Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Thu, 1 Sep 2016 10:13:01 -0700 Subject: [PATCH 23/31] cleanup and ditch legacy facts --- manifests/manage.pp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/manifests/manage.pp b/manifests/manage.pp index 2b7e3af..7341227 100644 --- a/manifests/manage.pp +++ b/manifests/manage.pp @@ -5,7 +5,7 @@ $type = 'mobileconfig', ) { - if $::operatingsystem != 'Darwin' { + if $facts['os']['name'] != 'Darwin' { fail('The mobileconfig::manage resource type is only supported on OS X') } @@ -15,20 +15,20 @@ mode => '0700', } - if ! defined(File["${::puppet_vardir}/mobileconfigs"]) { - file { "${::puppet_vardir}/mobileconfigs": + if ! defined(File["${facts['puppet_vardir']}/mobileconfigs"]) { + file { "${facts['puppet_vardir']}/mobileconfigs": ensure => directory, } } case $type { 'template': { - file { "${::puppet_vardir}/mobileconfigs/${name}": + file { "${facts['puppet_vardir']}/mobileconfigs/${name}": ensure => file, content => $file_source, } } default: { - file { "${::puppet_vardir}/mobileconfigs/${name}": + file { "${facts['puppet_vardir']}/mobileconfigs/${name}": ensure => file, source => $file_source, } @@ -36,10 +36,10 @@ } profile_manager { $name: - ensure => $ensure, - profile => "${::puppet_vardir}/mobileconfigs/${name}", - require => File["${::puppet_vardir}/mobileconfigs/${name}"], - subscribe => File["${::puppet_vardir}/mobileconfigs/${name}"], + ensure => $ensure, + profile => "${facts['puppet_vardir']}/mobileconfigs/${name}", + require => File["${facts['puppet_vardir']}/mobileconfigs/${name}"], + subscribe => File["${facts['puppet_vardir']}/mobileconfigs/${name}"], } From 2433c50c909ba1d4bbe8bd8af01f11fb3c27af00 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Fri, 23 Sep 2016 18:05:38 -0700 Subject: [PATCH 24/31] you might not have any profiles installed --- lib/facter/profiles.rb | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 052085c..bb1ca71 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -10,27 +10,31 @@ output = Facter::Util::Resolution.exec('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') - for item in Puppet::Util::Plist.parse_plist(output)[0]['_items'][0]['_items'] - profiles[item['spconfigprofile_profile_identifier']] = { - 'display_name' => item['_name'], - 'description' => item['spconfigprofile_description'], - 'verification_state' => item['spconfigprofile_verification_state'], - 'uuid' => item['spconfigprofile_profile_uuid'], - 'organization' => item['spconfigprofile_organization'], - 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first), - 'payload' => [] - } + data = Puppet::Util::Plist.parse_plist(output)[0]['_items'] - for pl in item['_items'] - profiles[item['spconfigprofile_profile_identifier']]['payload'] << { - 'name' => pl['_name'], - 'display_name' => pl['spconfigprofile_payload_display_name'], - 'identifier' => pl['spconfigprofile_payload_identifier'], - 'uuid' => pl['spconfigprofile_payload_uuid'], - # commented out because this is returned in old ASCII plist format - # which cfpropertylist cannot handle, so the data is useless. - # 'data' => pl['spconfigprofile_payload_data'], + unless data.empty? + for item in data[0]['_items'] + profiles[item['spconfigprofile_profile_identifier']] = { + 'display_name' => item['_name'], + 'description' => item['spconfigprofile_description'], + 'verification_state' => item['spconfigprofile_verification_state'], + 'uuid' => item['spconfigprofile_profile_uuid'], + 'organization' => item['spconfigprofile_organization'], + 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first), + 'payload' => [] } + + for pl in item['_items'] + profiles[item['spconfigprofile_profile_identifier']]['payload'] << { + 'name' => pl['_name'], + 'display_name' => pl['spconfigprofile_payload_display_name'], + 'identifier' => pl['spconfigprofile_payload_identifier'], + 'uuid' => pl['spconfigprofile_payload_uuid'], + # commented out because this is returned in old ASCII plist format + # which cfpropertylist cannot handle, so the data is useless. + # 'data' => pl['spconfigprofile_payload_data'], + } + end end end end From 4c00e0ac6725c4212f6f2d3ca21a758cfede446f Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Fri, 28 Oct 2016 13:00:57 -0700 Subject: [PATCH 25/31] Major fixes for ensure=> absent --- Modulefile | 11 --- README.md | 2 +- .../profile_manager/{osx.rb => macos.rb} | 15 +++-- manifests/manage.pp | 67 ++++++++++--------- metadata.json | 33 +++++++++ 5 files changed, 79 insertions(+), 49 deletions(-) delete mode 100644 Modulefile rename lib/puppet/provider/profile_manager/{osx.rb => macos.rb} (87%) create mode 100644 metadata.json diff --git a/Modulefile b/Modulefile deleted file mode 100644 index 729944c..0000000 --- a/Modulefile +++ /dev/null @@ -1,11 +0,0 @@ -name 'rcoleman-mac_profiles_handler' -version '0.3.0' -source 'git@github.com:ryanycoleman/rcoleman-mac_profiles_handler.git' -author 'ryanycoleman' -license 'Apache' -summary 'Puppet Module for managing OS X Configuration Profiles' -description 'This module provides two resource types for managing configuration profiles.' -project_page 'https://github.com/ryanycoleman/rcoleman-mac_profiles_handler' - -## Add dependencies, if any: -dependency 'puppetlabs/stdlib', '>= 2.3.1' diff --git a/README.md b/README.md index 29c78dd..e592084 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # mac_profiles_handler module for Puppet ## Description -This module provides two resource types for interacting with OS X configuration profiles. +This module provides two resource types for interacting with macOS configuration profiles. The profile_manager resource type is the back-end type that interacts with /usr/bin/profiles for creating, destroying and verifying a resource type. The mac_profiles_handler::manage resource type is user-facing and handles the management of the actual files. diff --git a/lib/puppet/provider/profile_manager/osx.rb b/lib/puppet/provider/profile_manager/macos.rb similarity index 87% rename from lib/puppet/provider/profile_manager/osx.rb rename to lib/puppet/provider/profile_manager/macos.rb index c5a075c..3153b94 100644 --- a/lib/puppet/provider/profile_manager/osx.rb +++ b/lib/puppet/provider/profile_manager/macos.rb @@ -1,7 +1,7 @@ require 'puppet/util/plist' -Puppet::Type.type(:profile_manager).provide :osx do - desc 'Provides management of mobileconfig profiles on OS X.' +Puppet::Type.type(:profile_manager).provide :macos do + desc 'Provides management of mobileconfig profiles on macOS.' confine operatingsystem: :darwin @@ -19,14 +19,15 @@ def destroy end def exists? - installed - end - - def installed # if already installed, check if it is the right one. # if not installed, return false. + # if we are removing, don't care if it is the right one. if Facter.value(:profiles).include? resource[:name] - return current + if resource[:ensure] == :absent + return true + else + return current + end else return false end diff --git a/manifests/manage.pp b/manifests/manage.pp index 7341227..61376d2 100644 --- a/manifests/manage.pp +++ b/manifests/manage.pp @@ -1,47 +1,54 @@ # manage mac profiles define mac_profiles_handler::manage( - $file_source, - $ensure, + $file_source = '', + $ensure = 'present', $type = 'mobileconfig', ) { if $facts['os']['name'] != 'Darwin' { - fail('The mobileconfig::manage resource type is only supported on OS X') + fail('The mobileconfig::manage resource type is only supported on macOS') } - File { - owner => 'root', - group => 'wheel', - mode => '0700', - } - - if ! defined(File["${facts['puppet_vardir']}/mobileconfigs"]) { - file { "${facts['puppet_vardir']}/mobileconfigs": - ensure => directory, - } - } - case $type { - 'template': { - file { "${facts['puppet_vardir']}/mobileconfigs/${name}": - ensure => file, - content => $file_source, + case $ensure { + 'absent': { + profile_manager { $name: + ensure => $ensure, } } default: { - file { "${facts['puppet_vardir']}/mobileconfigs/${name}": - ensure => file, - source => $file_source, + File { + owner => 'root', + group => 'wheel', + mode => '0700', } - } - } - profile_manager { $name: - ensure => $ensure, - profile => "${facts['puppet_vardir']}/mobileconfigs/${name}", - require => File["${facts['puppet_vardir']}/mobileconfigs/${name}"], - subscribe => File["${facts['puppet_vardir']}/mobileconfigs/${name}"], + if ! defined(File["${facts['puppet_vardir']}/mobileconfigs"]) { + file { "${facts['puppet_vardir']}/mobileconfigs": + ensure => directory, + } + } + case $type { + 'template': { + file { "${facts['puppet_vardir']}/mobileconfigs/${name}": + ensure => file, + content => $file_source, + } + } + default: { + file { "${facts['puppet_vardir']}/mobileconfigs/${name}": + ensure => file, + source => $file_source, + } + } + } + profile_manager { $name: + ensure => $ensure, + profile => "${facts['puppet_vardir']}/mobileconfigs/${name}", + require => File["${facts['puppet_vardir']}/mobileconfigs/${name}"], + subscribe => File["${facts['puppet_vardir']}/mobileconfigs/${name}"], + } + } } - } diff --git a/metadata.json b/metadata.json new file mode 100644 index 0000000..35d12bf --- /dev/null +++ b/metadata.json @@ -0,0 +1,33 @@ +{ + "name": "puppet-mac_profiles_handler", + "author": "", + "license": "", + "version": "2.0.0", + "summary": "Puppet Module for managing macOS Configuration Profiles", + "source": "https://github.com/keeleysam/puppet-mac_profiles_handler", + "project_page": "https://github.com/keeleysam/puppet-mac_profiles_handler", + "issues_url": "https://github.com/keeleysam/puppet-mac_profiles_handler/issues", + "tags": [ + "macOS", + "OS X", + "mobileconfig", + "profiles" + ], + "operatingsystem_support": [ + { + "operatingsystem": "Darwin" + } + ], + "requirements": [ + { + "name": "puppet", + "version_requirement": ">= 4.4.0" + } + ], + "dependencies": [ + { + "name": "puppetlabs/stdlib", + "version_requirement": ">= 2.3.1" + } + ] +} From 6590c7511187d25907488256ea5ae0cc34a403a1 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 31 Oct 2016 11:13:17 -0500 Subject: [PATCH 26/31] update readme --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index e592084..6d19e43 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,13 @@ mac_profiles_handler::manage { 'com.puppetlabs.myprofile': } +You can also ensure that a profile is absent by specifying just the identifier: +
+mac_profiles_handler::manage { '00000000-0000-0000-A000-4A414D460003':
+  ensure => absent,
+}
+
+ You must pass the profilers identifier as your namevar, ensure accepts present or absent and file_source behaves the same way source behaves for file. From bdb1e31aa751a0b7f8fc3723d3d56b9b7518547a Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Mon, 31 Oct 2016 12:36:15 -0500 Subject: [PATCH 27/31] rework, now gets state during run as it may change from other sources --- lib/puppet/provider/profile_manager/macos.rb | 50 +++++++++++--------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/lib/puppet/provider/profile_manager/macos.rb b/lib/puppet/provider/profile_manager/macos.rb index 3153b94..e6138ac 100644 --- a/lib/puppet/provider/profile_manager/macos.rb +++ b/lib/puppet/provider/profile_manager/macos.rb @@ -22,36 +22,29 @@ def exists? # if already installed, check if it is the right one. # if not installed, return false. # if we are removing, don't care if it is the right one. - if Facter.value(:profiles).include? resource[:name] + state = getinstalledstate + if state != false if resource[:ensure] == :absent return true else - return current + begin + return state['install_date'].to_time == getreceipts[resource[:name]]['install_date'] + rescue NoMethodError + # no matching receipt + return false + end end else return false end end - def getinstalleddate - # must be rerun as the output from Facter's earlier run is now - # outdated, but this only runs on refresh so not horrible. - output = Puppet::Util::Execution.execute('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') - - for item in Puppet::Util::Plist.parse_plist(output)[0]['_items'][0]['_items'] - if item['spconfigprofile_profile_identifier'] == resource[:name] - return DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first) - end - end - end - def getreceipts begin - receipts = Puppet::Util::Plist.read_plist_file(Facter.value(:puppet_vardir) + '/mobileconfigs/receipts.plist') + receipts = Puppet::Util::Plist.read_plist_file(Puppet[:vardir] + '/mobileconfigs/receipts.plist') rescue IOError, Errno::ENOENT receipts = {} end - receipts end @@ -61,15 +54,28 @@ def writereceipt # code from the fact but needs to re-run immediately. receipts = getreceipts - receipts[resource[:name]] = { 'install_date' => getinstalleddate } + receipts[resource[:name]] = { 'install_date' => getinstalledstate['install_date'] } - Puppet::Util::Plist.write_plist_file(receipts, Facter.value(:puppet_vardir) + '/mobileconfigs/receipts.plist') + Puppet::Util::Plist.write_plist_file(receipts, Puppet[:vardir] + '/mobileconfigs/receipts.plist') end - def current - return getinstalleddate.to_time == getreceipts[resource[:name]]['install_date'] - rescue NoMethodError - # no matching receipt + def getinstalledstate + output = Puppet::Util::Execution.execute('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') + + data = Puppet::Util::Plist.parse_plist(output)[0]['_items'] + + unless data.empty? + for item in data[0]['_items'] + if item['spconfigprofile_profile_identifier'] == resource[:name] + return { + 'identifier' => item['spconfigprofile_profile_identifier'], + 'display_name' => item['_name'], + 'uuid' => item['spconfigprofile_profile_uuid'], + 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first) + } + end + end + end return false end end From c147b0e62af332bc39bdb79cba82d5f2b3048199 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Tue, 15 Nov 2016 11:24:28 -0800 Subject: [PATCH 28/31] switch to use profiles instead of system profiler to hopefully work around some issues --- lib/facter/profiles.rb | 43 +++++++++++--------- lib/puppet/provider/profile_manager/macos.rb | 22 ++++++---- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index bb1ca71..a7b7448 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -1,5 +1,6 @@ require 'puppet/util/plist' require 'time' +require 'tmpdir' Facter.add(:profiles) do confine kernel: 'Darwin' @@ -8,31 +9,35 @@ if Facter.value(:os)['release']['major'].to_i >= 12 - output = Facter::Util::Resolution.exec('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') + path = Dir.mktmpdir + '/profiles.plist' - data = Puppet::Util::Plist.parse_plist(output)[0]['_items'] + # why???? + Facter::Util::Resolution.exec(['/usr/bin/profiles', '-C', '-o', path].join(' ')) + + plist = Puppet::Util::Plist.read_plist_file(path) + + data = plist['_computerlevel'] unless data.empty? - for item in data[0]['_items'] - profiles[item['spconfigprofile_profile_identifier']] = { - 'display_name' => item['_name'], - 'description' => item['spconfigprofile_description'], - 'verification_state' => item['spconfigprofile_verification_state'], - 'uuid' => item['spconfigprofile_profile_uuid'], - 'organization' => item['spconfigprofile_organization'], - 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first), + for item in data + profiles[item['ProfileIdentifier']] = { + 'display_name' => item['ProfileDisplayName'], + 'description' => item['ProfileDescription'], + 'verification_state' => item['ProfileVerificationState'], + 'uuid' => item['ProfileUUID'], + 'organization' => item['ProfileOrganization'], + 'type' => item['ProfileType'], + 'install_date' => DateTime.parse(item['ProfileInstallDate']), 'payload' => [] } - for pl in item['_items'] - profiles[item['spconfigprofile_profile_identifier']]['payload'] << { - 'name' => pl['_name'], - 'display_name' => pl['spconfigprofile_payload_display_name'], - 'identifier' => pl['spconfigprofile_payload_identifier'], - 'uuid' => pl['spconfigprofile_payload_uuid'], - # commented out because this is returned in old ASCII plist format - # which cfpropertylist cannot handle, so the data is useless. - # 'data' => pl['spconfigprofile_payload_data'], + for pl in item['ProfileItems'] + profiles[item['ProfileIdentifier']]['payload'] << { + 'type' => pl['PayloadType'], + 'identifier' => pl['PayloadIdentifier'], + 'uuid' => pl['PayloadUUID'], + # commented out for now because its not super useful. + # 'content' => pl['PayloadContent'], } end end diff --git a/lib/puppet/provider/profile_manager/macos.rb b/lib/puppet/provider/profile_manager/macos.rb index e6138ac..0366db4 100644 --- a/lib/puppet/provider/profile_manager/macos.rb +++ b/lib/puppet/provider/profile_manager/macos.rb @@ -1,4 +1,5 @@ require 'puppet/util/plist' +require 'tmpdir' Puppet::Type.type(:profile_manager).provide :macos do desc 'Provides management of mobileconfig profiles on macOS.' @@ -60,18 +61,23 @@ def writereceipt end def getinstalledstate - output = Puppet::Util::Execution.execute('/usr/sbin/system_profiler SPConfigurationProfileDataType -xml') + # profiles will only write to a nonexistant file, so we make a temp dir for it to write to. + path = Dir.mktmpdir + '/profiles.plist' - data = Puppet::Util::Plist.parse_plist(output)[0]['_items'] + Puppet::Util::Execution.execute(['/usr/bin/profiles', '-C', '-o', path]) + + plist = Puppet::Util::Plist.read_plist_file(path) + + data = plist['_computerlevel'] unless data.empty? - for item in data[0]['_items'] - if item['spconfigprofile_profile_identifier'] == resource[:name] + for item in data + if item['ProfileIdentifier'] == resource[:name] return { - 'identifier' => item['spconfigprofile_profile_identifier'], - 'display_name' => item['_name'], - 'uuid' => item['spconfigprofile_profile_uuid'], - 'install_date' => DateTime.parse(item['spconfigprofile_install_date'].scan(/\(([^\)]+)\)/).last.first) + 'identifier' => item['ProfileIdentifier'], + 'display_name' => item['ProfileDisplayName'], + 'uuid' => item['ProfileUUID'], + 'install_date' => DateTime.parse(item['ProfileInstallDate']) } end end From 753eb03723cff2ad15c1c2d404ecf82b76d13dd6 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Tue, 22 Nov 2016 14:10:08 -0600 Subject: [PATCH 29/31] handle case where no profiles installed --- lib/facter/profiles.rb | 6 ++---- lib/puppet/provider/profile_manager/macos.rb | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index a7b7448..284d452 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -16,10 +16,8 @@ plist = Puppet::Util::Plist.read_plist_file(path) - data = plist['_computerlevel'] - - unless data.empty? - for item in data + if plist.key?('_computerlevel') + for item in plist['_computerlevel'] profiles[item['ProfileIdentifier']] = { 'display_name' => item['ProfileDisplayName'], 'description' => item['ProfileDescription'], diff --git a/lib/puppet/provider/profile_manager/macos.rb b/lib/puppet/provider/profile_manager/macos.rb index 0366db4..22de902 100644 --- a/lib/puppet/provider/profile_manager/macos.rb +++ b/lib/puppet/provider/profile_manager/macos.rb @@ -68,10 +68,8 @@ def getinstalledstate plist = Puppet::Util::Plist.read_plist_file(path) - data = plist['_computerlevel'] - - unless data.empty? - for item in data + if plist.key?('_computerlevel') + for item in plist['_computerlevel'] if item['ProfileIdentifier'] == resource[:name] return { 'identifier' => item['ProfileIdentifier'], From c56c0f24059433707f0e46a9494d19eddd9e7cb9 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Wed, 17 Jan 2018 09:38:52 -0800 Subject: [PATCH 30/31] only require things if we are actually going to use them --- lib/facter/profiles.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index 284d452..af24dc7 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -1,10 +1,11 @@ -require 'puppet/util/plist' -require 'time' -require 'tmpdir' - Facter.add(:profiles) do confine kernel: 'Darwin' setcode do + + require 'puppet/util/plist' + require 'time' + require 'tmpdir' + profiles = {} if Facter.value(:os)['release']['major'].to_i >= 12 From 55b5e8c905b2cdaabccf3fa5e2880bc3522f7a88 Mon Sep 17 00:00:00 2001 From: Samuel Keeley Date: Tue, 27 Mar 2018 16:59:56 -0500 Subject: [PATCH 31/31] every day new things --- lib/facter/profiles.rb | 8 +------- lib/puppet/provider/profile_manager/macos.rb | 7 +------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/lib/facter/profiles.rb b/lib/facter/profiles.rb index af24dc7..60768aa 100644 --- a/lib/facter/profiles.rb +++ b/lib/facter/profiles.rb @@ -4,18 +4,12 @@ require 'puppet/util/plist' require 'time' - require 'tmpdir' profiles = {} if Facter.value(:os)['release']['major'].to_i >= 12 - path = Dir.mktmpdir + '/profiles.plist' - - # why???? - Facter::Util::Resolution.exec(['/usr/bin/profiles', '-C', '-o', path].join(' ')) - - plist = Puppet::Util::Plist.read_plist_file(path) + plist = Puppet::Util::Plist.parse_plist(Facter::Util::Resolution.exec(['/usr/bin/profiles', '-C', '-o', 'stdout-xml'].join(' '))) if plist.key?('_computerlevel') for item in plist['_computerlevel'] diff --git a/lib/puppet/provider/profile_manager/macos.rb b/lib/puppet/provider/profile_manager/macos.rb index 22de902..0b191b3 100644 --- a/lib/puppet/provider/profile_manager/macos.rb +++ b/lib/puppet/provider/profile_manager/macos.rb @@ -1,5 +1,4 @@ require 'puppet/util/plist' -require 'tmpdir' Puppet::Type.type(:profile_manager).provide :macos do desc 'Provides management of mobileconfig profiles on macOS.' @@ -61,12 +60,8 @@ def writereceipt end def getinstalledstate - # profiles will only write to a nonexistant file, so we make a temp dir for it to write to. - path = Dir.mktmpdir + '/profiles.plist' - Puppet::Util::Execution.execute(['/usr/bin/profiles', '-C', '-o', path]) - - plist = Puppet::Util::Plist.read_plist_file(path) + plist = Puppet::Util::Plist.parse_plist(Puppet::Util::Execution.execute(['/usr/bin/profiles', '-C', '-o', 'stdout-xml'])) if plist.key?('_computerlevel') for item in plist['_computerlevel']