Permalink
Switch branches/tags
0.9-stable 2.6 10-stable 10.16.4-release 10.16.6 10.24-patch 11-stable 11.4-patch 11.9 11.18.0.r 12.2-stable 12.4-stable 12.5-stable 12.6-release 13.9 CHEF-3557 CHEF-4123 IPO-44/td-mc/add-node-uuid ISSUE/3871 ad/3888 adamedx/alternate-user-execute adamedx/alternate-user-remote-file adamedx/alternate-user adamedx/remote-file-windows-user adamedx/windows-execute-user adamleff/messages_as_module adamleff/test-bff-branch allow-tokenless-chef-solo-data-collector archive_file audit auto_dependency_bump_test azure-pipelines backport-diff-disable bp-423/git-stunnel bp-423/stunnel-in-rhel btm/MSYS-752_build btm/secrets-spike btm/target-mode bump_15 cd/artifacts-cheffs cd/nuke-pedant cd/upgrade-pedant cd/validate-zero-policyfile-routes chef-12 chef-13 chef-14 chef-nolan/double-stdout chef-revert-6773-revert-6770-tm/ruby_25 cheffish ci-playground consistent_timeout_usage dan/verify-partial-doubles debug_logging debug debugging-travis-things default_env doc_generator expeditor/mixlib-shellout_2.4.4 gem git-config-fix jcam/remote_file jdm/ruby21 jdm/sign-v1.3 jdm/test-ci jdm/win-package-remote jeremymv2/chef_fs_normalize_has jk/block-property jk/client_madness jk/cookbook-processor jk/dsl_modules_instead_of_maps jk/easier_chef_fs jk/file-resource jk/nobuild jk/recipe_block jk/revert-user_home jk/script-properties jk/service-properties jk/split-cookbooks jk/test-warnings jq/test_train_gcp jsinha/BEN-123-IPS-LINKS jsinha/fix_solaris_service jsinha/test_rust_update ksubrama/msys2 lcg/add-test-segment lcg/add-yum-tests lcg/attribute-debug lcg/attributes-on-12.4.1-for-phil lcg/attributes-v1.99 lcg/bump-bundler lcg/chef-12-yum-backport lcg/chef-13-attr-on-chef-12 lcg/chef-appbundle-locking lcg/cnetos-6-func-tests lcg/de-lazy-attributes lcg/debugging-ffi lcg/deep-merge-cache-backport lcg/deep-merge-testing lcg/deprecate-chef-solo-legacy-mode lcg/deprecate-vendor lcg/dnf-install-supercharging lcg/e-g-only-use-inline-resources lcg/fix-windows-hostname-validation lcg/flip-chef-gem-default lcg/functest-apt-update-failure-behavior2 lcg/gc-inspection lcg/git lcg/improve-appbundling lcg/just-testing2 lcg/learnchef-tests lcg/openssl-sitelibdir lcg/pg-gem lcg/pr-3778 lcg/recipe-resource lcg/refreeze-chef-12 lcg/resolv-replace lcg/resource-sugar lcg/rfc-045 lcg/rollback-acceptance-bumps lcg/splice-chef-into-external-tests lcg/testing2 lcg/tight-coupling1 lcg/turbo-merge-backport lcg/turbo-merge lcg/unused-resource-collection-apis lcg/yum-new-resource lcg/yum_package_repo_opts lita-acceptance lita-dev master mdadm_cr mh/missing_profile mh/recover multi_package nano nls/ftp-proxy nls/proxy-bug ohai-7 omnibus-test opensuse_leap_15_testing php pw/mixlib-install-2.0.2 rack-spec-compliance rb-readline reboot_resource release_12.10.24 response_file revert-6776-revert-6766-lcg/windows-interval revert rhass/COOL-502_clean rhass/COOL-611 rhass/chef-12/update-all-the-things rhass/maintainers rhass/minibus rhass/test-openssl-nocomp-branch rhass/12.15.0 rm-active-support ryan/knife_ssh_row ryan/profiling salam/acceptance salam/knife-ssh-tweak salam/test-revert schisamo/angrychef-12.6.0 sensitive-file-tests sersut/attr-stress-test-w-reads sersut/bundler-test sersut/test-CI-31 shain/test_aix_thing shain/test_extra_fips shain/test_solaris_random shain/verificate_pkg shain/whatishthis2 shain/whatsthis ssd-sr/re-raise-system-exit-playground ssd/CHEF-3068-rebased ssd/libiconv-test-branch status_done_right stupid1 tduffield/add-label-version-bumping tduffield/auth-proxy-tests tduffield/bump-deps-for-cheffish tduffield/openssl-override tduffield/supress-hashie-logging tduffield/update-gems-for-net-ssh test-chef-acceptance-pr-31 test-parallel-suites test-securable-on-file-create tm/archive_winning tm/circle tm/fix_win_xslt tm/lazy tm/revert_mount_properties tm/ruby_25 tm/systemd_networkd tm/test_omnibus_fix tm/test_12_pipelines tm/user_refactor top_choc trusted try_ec2 update-omnibus-libs user_properties v12.11.18 v12.19.37 v12.19.38 v13.1.3 win64 winrm_pre yzl/ES-437
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
252 lines (224 sloc) 7.89 KB
#
# Author:: Nate Walck (<nate.walck@gmail.com>)
# Copyright:: Copyright 2015-2016, Facebook, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require "chef/log"
require "chef/provider"
require "chef/resource"
require "chef/resource/file"
require "uuidtools"
class Chef
class Provider
class OsxProfile < Chef::Provider
provides :osx_profile
provides :osx_config_profile
def load_current_resource
@current_resource = Chef::Resource::OsxProfile.new(new_resource.name)
current_resource.profile_name(new_resource.profile_name)
all_profiles = get_installed_profiles
new_resource.profile(
new_resource.profile ||
new_resource.profile_name
)
@new_profile_hash = get_profile_hash(new_resource.profile)
if @new_profile_hash
@new_profile_hash["PayloadUUID"] =
config_uuid(@new_profile_hash)
end
if @new_profile_hash
@new_profile_identifier = @new_profile_hash["PayloadIdentifier"]
else
@new_profile_identifier = new_resource.identifier ||
new_resource.profile_name
end
current_profile = nil
if all_profiles && all_profiles.key?("_computerlevel")
current_profile = all_profiles["_computerlevel"].find do |item|
item["ProfileIdentifier"] == @new_profile_identifier
end
end
current_resource.profile(current_profile)
end
def define_resource_requirements
requirements.assert(:remove) do |a|
if @new_profile_identifier
a.assertion do
!@new_profile_identifier.nil? &&
!@new_profile_identifier.end_with?(".mobileconfig") &&
/^\w+(?:(\.| )\w+)+$/.match(@new_profile_identifier)
end
a.failure_message RuntimeError, "when removing using the identifier property, it must match the profile identifier"
else
new_profile_name = new_resource.profile_name
a.assertion do
!new_profile_name.end_with?(".mobileconfig") &&
/^\w+(?:(\.| )\w+)+$/.match(new_profile_name)
end
a.failure_message RuntimeError, "When removing by resource name, it must match the profile identifier "
end
end
requirements.assert(:install) do |a|
if @new_profile_hash.is_a?(Hash)
a.assertion do
@new_profile_hash.include?("PayloadIdentifier")
end
a.failure_message RuntimeError, "The specified profile does not seem to be valid"
end
if @new_profile_hash.is_a?(String)
a.assertion do
@new_profile_hash.end_with?(".mobileconfig")
end
a.failure_message RuntimeError, "#{new_profile_hash}' is not a valid profile"
end
end
end
def action_install
unless profile_installed?
converge_by("install profile #{@new_profile_identifier}") do
profile_path = write_profile_to_disk
install_profile(profile_path)
get_installed_profiles(true)
end
end
end
def action_remove
# Clean up profile after removing it
if profile_installed?
converge_by("remove profile #{@new_profile_identifier}") do
remove_profile
get_installed_profiles(true)
end
end
end
def load_profile_hash(new_profile)
# file must exist in cookbook
if new_profile.end_with?(".mobileconfig")
unless cookbook_file_available?(new_profile)
error_string = "#{self}: '#{new_profile}' not found in cookbook"
raise Chef::Exceptions::FileNotFound, error_string
end
cookbook_profile = cache_cookbook_profile(new_profile)
read_plist(cookbook_profile)
else
nil
end
end
def cookbook_file_available?(cookbook_file)
run_context.has_cookbook_file_in_cookbook?(
new_resource.cookbook_name, cookbook_file
)
end
def get_cache_dir
cache_dir = Chef::FileCache.create_cache_path(
"profiles/#{new_resource.cookbook_name}"
)
end
def cache_cookbook_profile(cookbook_file)
Chef::FileCache.create_cache_path(
::File.join(
"profiles",
new_resource.cookbook_name,
::File.dirname(cookbook_file)
)
)
remote_file = Chef::Resource::CookbookFile.new(
::File.join(
get_cache_dir,
"#{cookbook_file}.remote"
),
run_context
)
remote_file.cookbook_name = new_resource.cookbook_name
remote_file.source(cookbook_file)
remote_file.backup(false)
remote_file.run_action(:create)
remote_file.path
end
def get_profile_hash(new_profile)
if new_profile.is_a?(Hash)
new_profile
elsif new_profile.is_a?(String)
load_profile_hash(new_profile)
end
end
def config_uuid(profile)
# Make a UUID of the profile contents and return as string
UUIDTools::UUID.sha1_create(
UUIDTools::UUID_DNS_NAMESPACE,
profile.to_s
).to_s
end
def write_profile_to_disk
new_resource.path(Chef::FileCache.create_cache_path("profiles"))
tempfile = Chef::FileContentManagement::Tempfile.new(new_resource).tempfile
tempfile.write(@new_profile_hash.to_plist)
tempfile.close
tempfile.path
end
def install_profile(profile_path)
cmd = [ "/usr/bin/profiles", "-I", "-F", profile_path ]
logger.trace("cmd: #{cmd.join(" ")}")
shellout_results = shell_out(*cmd)
shellout_results.exitstatus
end
def remove_profile
cmd = [ "/usr/bin/profiles", "-R", "-p", @new_profile_identifier ]
logger.trace("cmd: #{cmd.join(" ")}")
shellout_results = shell_out(*cmd)
shellout_results.exitstatus
end
def get_installed_profiles(update = nil)
if update
node.run_state[:config_profiles] = query_installed_profiles
else
node.run_state[:config_profiles] ||= query_installed_profiles
end
end
def query_installed_profiles
# Dump all profile metadata to a tempfile
tempfile = generate_tempfile
write_installed_profiles(tempfile)
installed_profiles = read_plist(tempfile)
logger.trace("Saved profiles to run_state")
# Clean up the temp file as we do not need it anymore
::File.unlink(tempfile)
installed_profiles
end
def generate_tempfile
tempfile = ::Dir::Tmpname.create("allprofiles.plist") {}
end
def write_installed_profiles(tempfile)
shell_out!( "/usr/bin/profiles", "-P", "-o", tempfile )
end
def read_plist(xml_file)
Plist.parse_xml(xml_file)
end
def profile_installed?
# Profile Identifier and UUID must match a currently installed profile
if current_resource.profile.nil? || current_resource.profile.empty?
false
else
if new_resource.action.include?(:remove)
true
else
current_resource.profile["ProfileUUID"] ==
@new_profile_hash["PayloadUUID"]
end
end
end
end
end
end