chef/cookbooks/cpe_workspaceone/resources/cpe_workspaceone.rb (161 lines of code) (raw):
#
# Cookbook:: cpe_workspaceone
# Resources:: cpe_workspaceone
#
# vim: syntax=ruby:expandtab:shiftwidth=2:softtabstop=2:tabstop=2
#
# Copyright:: (c) 2019-present, Uber Technologies, Inc.
# All rights reserved.
#
# This source code is licensed under the Apache 2.0 license found in the
# LICENSE file in the root directory of this source tree.
#
unified_mode true
resource_name :cpe_workspaceone
provides :cpe_workspaceone, :os => 'darwin'
default_action :manage
action :manage do
# manage needs to go first if you are attempting to hide the agent from appearing showing it's UX to users.
manage if manage?
install if install?
manage_cli_config if manage_cli_config?
enforce_mdm_profiles if enforce_mdm_profiles?
uninstall if !install? && uninstall?
end
action_class do # rubocop:disable Metrics/BlockLength
WS1_DEFAULT_PREFS = {
'checkin-interval' => 60,
'menubar-icon' => true,
'sample-interval' => 60,
'transmit-interval' => 60,
}.freeze
def enforce_mdm_profiles?
node['cpe_workspaceone']['mdm_profiles']['enforce']
end
def install?
node['cpe_workspaceone']['install']
end
def manage?
node['cpe_workspaceone']['manage']
end
def manage_cli_config?
node['cpe_workspaceone']['manage_cli']
end
def uninstall?
node['cpe_workspaceone']['uninstall']
end
def enforce_mdm_profiles
return unless node['cpe_workspaceone']['mdm_profiles']['enforce']
macos_enforce_mdm_profiles if macos?
end
def set_cli_config(flag, val)
default = WS1_DEFAULT_PREFS[flag]
val ||= default
cmd = node.hubcli_execute("config --set #{flag} #{val}")
unless cmd.exitstatus.zero?
if !cmd.stderr.include?('Error: Invalid value for option') || val == default
cmd.error!
end
Chef::Log.warn("cpe_workspaceone - #{cmd.stderr.strip} (#{val}) - setting default")
set_cli_config(flag, default)
end
end
def manage_cli_config
unless node.ws1_hubcli_exists
Chef::Log.warn('cpe_workspaceone - hubcli path does not exist, cannot enforce MDM profiles!')
return
end
prefs = node['cpe_workspaceone']['cli_prefs'].compact
prefs.each do |flag, val|
unless WS1_DEFAULT_PREFS.key?(flag)
Chef::Log.warn("cpe_workspaceone - refusing to manage unknown cli preference '#{flag}'")
next
end
set_cli_config(flag, val)
end
end
def macos_enforce_mdm_profiles
# Bail if path doesn't exist
unless node.ws1_hubcli_exists
Chef::Log.warn('cpe_workspaceone - hubcli path does not exist, cannot enforce MDM profiles!')
return
end
device_forcelist = node['cpe_workspaceone']['mdm_profiles']['profiles']['device_forced'] || []
# Bail if there are no device attributes
device_attributes = node.ws1_device_attributes
return if device_attributes.empty? || device_attributes.nil?
# Loop through the enforced device profiles and compare with available profiles from MDM
enforced_device_ws1_profiles = node['cpe_workspaceone']['mdm_profiles']['profiles']['device']
device_attributes['DeviceProfiles'].each do |ws1_profile|
profile_name = ws1_profile['Name']
profile_id = ws1_profile['Id'].to_s
profile_version = ws1_profile['CurrentVersion'].to_s
# WS1 dynamically creates the DisplayName by taking the Name of the profile and how many revisions have been
# done in the console. To make this simpler on the chef admin, we will concatenate the strings.
installed_profile_name = profile_name + '/V_' + profile_version
# Because of user/device level profiles being in one array, we need the if statement outside of the execute block
if enforced_device_ws1_profiles.include?(profile_name)
execute "Sending #{profile_name} for device installation to Workspace One console" do
command node.hubcli_cmd("profiles --install #{profile_id}")
only_if { node.ws1_hubcli_exists } # non-gsub or guard will fail.
not_if do
node.profile_installed?('ProfileDisplayName', installed_profile_name) && \
!device_forcelist.include?(profile_name)
end
timeout node['cpe_workspaceone']['hubcli_timeout']
end
end
end
user_forcelist = node['cpe_workspaceone']['mdm_profiles']['profiles']['user_forced'] || []
# Loop through the enforced user profiles and compare with available profiles from MDM
enforced_user_ws1_profiles = node['cpe_workspaceone']['mdm_profiles']['profiles']['user']
# Current version of hubcli API returns only DeviceProfiles, no such thing as UserProfiles, so we must be clever
# here and just do intelligent checks.
device_attributes['DeviceProfiles'].each do |ws1_profile|
profile_name = ws1_profile['Name']
profile_id = ws1_profile['Id'].to_s
profile_version = ws1_profile['CurrentVersion'].to_s
# WS1 dynamically creates the DisplayName by taking the Name of the profile and how many revisions have been
# done in the console. To make this simpler on the chef admin, we will concatenate the strings.
installed_profile_name = profile_name + '/V_' + profile_version
# Because of user/device level profiles being in one array, we need the if statement outside of the execute block
if enforced_user_ws1_profiles.include?(profile_name)
execute "Sending #{profile_name} for user installation to Workspace One console" do
command node.hubcli_cmd("profiles --install #{profile_id}")
only_if { node.ws1_hubcli_exists } # non-gsub or guard will fail.
not_if do
node.user_profile_installed?('ProfileDisplayName', installed_profile_name) && \
!user_forcelist.include?(profile_name)
end
timeout node['cpe_workspaceone']['hubcli_timeout']
end
end
end
end
def install
return unless node['cpe_workspaceone']['install']
macos_install if macos?
end
def macos_install
ws1_pkg_version = node['cpe_workspaceone']['pkg']['version']
ws1_pkg_allow_downgrade = node['cpe_workspaceone']['pkg']['allow_downgrade']
# Dumb workaround because WS1 Beta release versions contain a space.
if ws1_pkg_version.include?(' ')
Chef::Log.warn('cpe_workspaceone - package version contains a space! This is more than likely due to a beta '\
'release. Forcing allow_downgrade to true to prevent Chef failures with cpe_remote.')
ws1_pkg_allow_downgrade = true
end
cpe_remote_pkg 'Workspace One Agent' do
allow_downgrade ws1_pkg_allow_downgrade
app node['cpe_workspaceone']['pkg']['app_name']
checksum node['cpe_workspaceone']['pkg']['checksum']
pkg_name node['cpe_workspaceone']['pkg']['pkg_name'] if node['cpe_workspaceone']['pkg']['pkg_name']
pkg_url node['cpe_workspaceone']['pkg']['pkg_url'] if node['cpe_workspaceone']['pkg']['pkg_url']
receipt node['cpe_workspaceone']['pkg']['receipt']
version ws1_pkg_version
unless node['cpe_workspaceone']['pkg']['headers'].nil?
headers node['cpe_workspaceone']['pkg']['headers']
end
end
end
def manage
return unless node['cpe_workspaceone']['manage']
macos_manage if macos?
end
def macos_manage
ws1agent_prefs = node['cpe_workspaceone']['prefs'].compact
unless ws1agent_prefs.empty?
ws1agent_prefs.each_key do |key|
next if ws1agent_prefs[key].nil?
# WS1 agent doesn't use profiles atm. Chef 14+
if node.at_least_chef14?
macos_userdefaults "Configure com.vmware.hub.agent - #{key}" do
domain '/Library/Preferences/com.vmware.hub.agent'
key key
value ws1agent_prefs[key]
end
end
end
end
end
def uninstall
return unless node['cpe_workspaceone']['uninstall']
macos_uninstall if macos?
end
def macos_uninstall
# TODO: need to write
return
end
end