lib/jss/api_object/policy.rb in ruby-jss-1.2.10 vs lib/jss/api_object/policy.rb in ruby-jss-1.3.2
- old
+ new
@@ -172,11 +172,13 @@
MGMT_ACCOUNT_ACTIONS = {
no_change: 'doNotChange',
change_pw: 'specified',
generate_pw: 'random',
enable_fv2: 'fileVaultEnable',
- disable_fv2: 'fileVaultDisable'
+ disable_fv2: 'fileVaultDisable',
+ reset_random: 'resetRandom',
+ reset_pw: 'reset'
}.freeze
PACKAGE_ACTIONS = {
install: 'Install',
remove: 'Uninstall',
@@ -189,10 +191,16 @@
before: 'Before',
post: 'After',
after: 'After'
}.freeze
+ DISK_ENCRYPTION_ACTIONS = {
+ apply: "apply",
+ remediate: "remediate",
+ none: "none"
+ }
+
PRINTER_ACTIONS = {
map: 'install',
unmap: 'uninstall'
}.freeze
@@ -539,10 +547,11 @@
# @return [String] the message shown the user at policy start
attr_reader :user_message_start
# @return [String] the message shown the user at policy end
attr_reader :user_message_finish
+ alias user_message_end user_message_finish
# @return [Hash]
#
# Reboot options for the policy
#
@@ -668,10 +677,11 @@
@dock_items = @init_data[:dock_items]
@disk_encryption = @init_data[:disk_encryption]
@printers = @init_data[:printers]
+ @printers.shift
# Not in jss yet
end
# set non-nil defaults
@@ -912,10 +922,34 @@
@reboot_options[:message] = message
@need_to_update = true
end
alias message= reboot_message=
+ # Set User Start Message
+ #
+ # @param user_message[String] Text of User Message
+ #
+ # @return [void] description of returned object
+ def user_message_start=(message)
+ raise JSS::InvalidDataError, 'User message must be a String' unless message.is_a? String
+ @user_message_start = message
+ @need_to_update = true
+ end
+
+ # Set User Finish Message
+ #
+ # @param user_message[String] Text of User Message
+ #
+ # @return [void] description of returned object
+ def user_message_end=(message)
+ raise JSS::InvalidDataError, 'User message must be a String' unless message.is_a? String
+ @user_message_finish = message
+ @need_to_update = true
+ end
+
+ alias user_message_finish= user_message_end=
+
# Set Startup Disk
# Only Supports 'Specify Local Startup Disk' at the moment
#
# @param startup_disk_option[String]
#
@@ -1178,11 +1212,11 @@
@packages
end
# Remove a package from this policy by name or id
#
- # @param identfier [String,Integer] the name or id of the package to remove
+ # @param identifier [String,Integer] the name or id of the package to remove
#
# @return [Array, nil] the new packages array or nil if no change
#
def remove_package(identifier)
removed = @packages.delete_if { |p| p[:id] == identifier || p[:name] == identifier }
@@ -1268,11 +1302,11 @@
@scripts
end
# Remove a script from this policy by name or id
#
- # @param identfier [String,Integer] the name or id of the script to remove
+ # @param identifier [String,Integer] the name or id of the script to remove
#
# @return [Array, nil] the new scripts array or nil if no change
#
def remove_script(identifier)
removed = @scripts.delete_if { |s| s[:id] == identifier || s[:name] == identifier }
@@ -1290,10 +1324,53 @@
# @return [Array] the names of the directory_bindings handled by the policy
def directory_binding_names
@directory_bindings.map { |p| p[:name] }
end
+ # Add a Directory Bidning to the list of directory_bindings handled by this policy.
+ # If the directory binding already exists in the policy, nil is returned and
+ # no changes are made.
+ #
+ # @param [String,Integer] identifier the name or id of the directory binding to add to this policy
+ #
+ # @param position [Symbol, Integer] where to add this directory binding among the list of
+ # directory_bindings. Zero-based, :start and 0 are the same, as are :end and -1.
+ # Defaults to :end
+ #
+ # @return [Array, nil] the new @directory_bindings array, nil if directory_binding was already in the policy
+ #
+ def add_directory_binding(identifier, **opts)
+ id = validate_directory_binding_opts identifier, opts
+
+ return nil if @directory_bindings.map { |s| s[:id] }.include? id
+
+ name = JSS::DirectoryBinding.map_all_ids_to(:name, api: @api)[id]
+
+ directory_binding_data = {
+ id: id,
+ name: name
+ }
+
+ @directory_bindings.insert opts[:position], directory_binding_data
+
+ @need_to_update = true
+ @directory_bindings
+ end
+
+
+ # Remove a directory binding from this policy by name or id
+ #
+ # @param identifier [String,Integer] the name or id of the directory binding to remove
+ #
+ # @return [Array, nil] the new directory bindings array or nil if no change
+ #
+ def remove_directory_binding(identifier)
+ removed = @directory_bindings.delete_if { |s| s[:id] == identifier || s[:name] == identifier }
+ @need_to_update = true if removed
+ removed
+ end
+
###### Dock items
# @return [Array] the id's of the dock_items handled by the policy
def dock_item_ids
@dock_items.map { |p| p[:id] }
@@ -1302,28 +1379,232 @@
# @return [Array] the names of the dock_items handled by the policy
def dock_item_names
@dock_items.map { |p| p[:name] }
end
+
+ ###### Printers
+
+ # Add a specific printer object to the policy.
+ #
+ # @author Tyler Morgan
+ #
+ # @param newvalue [String,Integer] The name or the id of the printer to be added to this policy.
+ #
+ # @param position [Symbol, Integer] where to add this printer object among the list of printer
+ # objects. Zero-based, :start and 0 are the same, as are :end and -1.
+ # Defaults to :end
+ #
+ # @param action [Symbol] One of the PRINTER_ACTIONS symbols. What you want done with the printer object upon policy execution.
+ #
+ # @param make_default [TrueClass,FalseClass] Should this printer object be set to default.
+ # Defaults to false
+ #
+ # @return [String] The new printers array or nil if the printer was already in the policy
+ def add_printer(identifier, **opts)
+ id = validate_printer_opts identifier, opts
+
+ return nil if @printers.map { |p| p[:id] }.include? id
+
+ name = JSS::Printer.map_all_ids_to(:name, api: @api)[id]
+
+ printer_data = {
+ id: id,
+ name: name,
+ action: PRINTER_ACTIONS[opts[:action]],
+ make_default: opts[:make_default]
+ }
+
+ @printers.insert opts[:position], printer_data
+
+ @need_to_update = true
+ @printers
+ end
+
+
+ # Remove a specific printer object from the policy.
+ #
+ # @author Tyler Morgan
+ #
+ # @param identifier [String,Integer] The name or id of the printer to be removed.
+ #
+ # @return [Array, nil] The new printers array or nil if no change.
+ def remove_printer(identifier)
+ removed = @printers.delete_if { |p| p[:id] == identifier || p[:name] == identifier }
+
+ @need_to_update = true
+ removed
+ end
+
+ # Add a dock item to the policy
+ def add_dock_item(identifier, action)
+ id = JSS::DockItem.valid_id identifier, api: @api
+
+ raise JSS::NoSuchItemError, "No Dock Item matches '#{identifier}'" unless id
+
+ raise JSS::InvalidDataError, "Action must be one of: :#{DOCK_ITEM_ACTIONS.keys.join ', :'}" unless DOCK_ITEM_ACTIONS.include? action
+
+ return nil if @dock_items.map { |d| d[:id] }.include? id
+
+ name = JSS::DockItem.map_all_ids_to(:name, api: @api)[id]
+
+ @dock_items << {id: id, name: name, action: DOCK_ITEM_ACTIONS[action]}
+
+ @need_to_update = true
+ @dock_items
+ end
+
+ # Remove a dock item from the policy
+ def remove_dock_item(identifier)
+ # TODO: Add validation against JSS::DockItem
+ removed = @dock_items.delete_if { |d| d[:id] == identifier || d[:name] == identifier }
+ @need_to_update = true if removed
+ removed
+ end
+
# @return [Array] the id's of the printers handled by the policy
def printer_ids
begin
@printers.map { |p| p[:id] }
rescue TypeError
return []
end
end
-
+
# @return [Array] the names of the printers handled by the policy
def printer_names
begin
@printers.map { |p| p[:name] }
rescue TypeError
return []
end
end
+
+
+ ###### Disk Encryption
+
+ # Sets the Disk Encryption application to "Remediate" and sets the remediation key type to individual.
+ #
+ # @author Tyler Morgan
+ #
+ # @return [Void]
+ #
+ def reissue_key()
+ if @disk_encryption[:action] != DISK_ENCRYPTION_ACTIONS[:remediate]
+ # Setting New Action
+ hash = {
+ action: DISK_ENCRYPTION_ACTIONS[:remediate],
+ remediate_key_type: "Individual"
+ }
+
+ @disk_encryption = hash
+ @need_to_update = true
+
+ else
+ # Update
+ return
+ end
+
+ end
+
+
+ # Sets the Disk Encryption application to "Apply" and sets the correct disk encryption configuration ID using either the name or id.
+ #
+ # @author Tyler Morgan
+ #
+ # @return [Void]
+ #
+ def apply_encryption_configuration(identifier)
+
+ id = JSS::DiskEncryptionConfiguration.valid_id identifier
+
+ return if id.nil?
+
+ hash = {
+ action: DISK_ENCRYPTION_ACTIONS[:apply],
+ disk_encryption_configuration_id: id,
+ auth_restart: false
+ }
+
+ @disk_encryption = hash
+ @need_to_update = true
+ end
+
+
+ # Removes the Disk Encryption settings associated with this specific policy.
+ #
+ # @author Tyler Morgan
+ #
+ # @return [Void]
+ #
+ def remove_encryption_configuration()
+ hash = {
+ action: DISK_ENCRYPTION_ACTIONS[:none]
+ }
+
+ @disk_encryption = hash
+ @need_to_update = true
+ end
+
+ # Interact with management account settings
+ #
+ # @param action [Key] one of the MGMT_ACCOUNT_ACTIONS keys
+ #
+ # @return The current specified management settings.
+ #
+ # Reference: https://developer.jamf.com/documentation#resources-with-passwords
+ #
+ def set_management_account(action, **opts)
+ # TODO: Add proper error handling
+ raise JSS::InvalidDataError, "Action must be one of: :#{MGMT_ACCOUNT_ACTIONS.keys.join ', :'}" unless MGMT_ACCOUNT_ACTIONS.include? action
+
+ management_data = {}
+
+ if action == :change_pw || action == :reset_pw
+ raise JSS::MissingDataError, ":password must be provided when changing management account password" if opts[:password].nil?
+
+ management_data = {
+ action: MGMT_ACCOUNT_ACTIONS[action],
+ managed_password: opts[:password]
+ }
+ elsif action == :reset_random || action == :generate_pw
+ raise JSS::MissingDataError, ":password_length must be provided when setting a random password" if opts[:password_length].nil?
+ raise JSS::InvalidDataError, ":password_length must be an Integer" unless opts[:password_length].is_a? Integer
+
+ management_data = {
+ action: MGMT_ACCOUNT_ACTIONS[action],
+ managed_password_length: opts[:password_length]
+ }
+ else
+ management_data = {
+ action: MGMT_ACCOUNT_ACTIONS[action]
+ }
+ end
+
+ @management_account = management_data
+
+ @need_to_update = true
+
+ @management_account
+
+ end
+
+ # Check if management password matches provided password
+ #
+ # @param password[String] the password that is SHA256'ed to compare to the one from the API.
+ #
+ # @return [Boolean] The result of the comparison of the management password and provided text.
+ #
+ def verify_management_password(password)
+ raise JSS::InvalidDataError, "Management password must be a string." unless password.is_a? String
+
+ raise JSS::UnsupportedError, "'#{@management_account[:action].to_s}' does not support management passwords." unless @management_account[:action] == MGMT_ACCOUNT_ACTIONS[:change_pw] || @management_account[:action] == MGMT_ACCOUNT_ACTIONS[:reset_pw]
+
+ return Digest::SHA256.hexdigest(password).to_s == @management_account[:managed_password_sha256].to_s
+ end
+
###### Actions
# Try to execute this policy on this machine.
#
# @param show_output[Boolean] should the stdout and stderr of the
@@ -1437,10 +1718,68 @@
id = JSS::Script.valid_id identifier, api: @api
raise JSS::NoSuchItemError, "No script matches '#{identifier}'" unless id
id
end
+ # raise an error if the directory binding being added isn't valid
+ #
+ # @see #add_directory_binding
+ #
+ # @return [Integer, nil] the valid id for the package
+ #
+ def validate_directory_binding_opts(identifier, opts)
+ opts[:position] ||= -1
+
+ opts[:position] =
+ case opts[:position]
+ when :start then 0
+ when :end then -1
+ else JSS::Validate.integer(opts[:position])
+ end
+
+ # if the given position is past the end, set it to -1 (the end)
+ opts[:position] = -1 if opts[:position] > @directory_bindings.size
+
+ id = JSS::DirectoryBinding.valid_id identifier, api: @api
+ raise JSS::NoSuchItemError, "No directory binding matches '#{identifier}'" unless id
+ id
+ end
+
+ # Raises an error if the printer being added isn't valid, additionally checks the options and sets defaults where possible.
+ #
+ # @see #add_printer
+ #
+ # @return [Integer, nil] the valid id for the package
+ #
+ def validate_printer_opts(identifier, opts)
+ opts[:position] ||= -1
+
+ opts[:position] =
+ case opts[:position]
+ when :start then 0
+ when :end then -1
+ else JSS::Validate.integer(opts[:position])
+ end
+
+ # If the given position is past the end, set it to -1 (the end)
+ opts[:position] = -1 if opts[:position] > @printers.size
+
+ # Checks if action to be done with the printer object is provided and valid.
+ raise JSS::MissingDataError, "action must be provided, must be one of :#{PRINTER_ACTIONS.keys.join(':,')}." if opts[:action].nil?
+ raise JSS::InvalidDataError, "action must be one of :#{PRINTER_ACTIONS.keys.join(',:')}." unless PRINTER_ACTIONS.keys.include? opts[:action]
+
+
+ # Checks if the make_default option is valid, and sets the default if needed.
+ raise JSS::InvalidDataError, "make_default must be either true or false." unless opts[:make_default].is_a?(TrueClass) || opts[:make_default].is_a?(FalseClass) || opts[:make_default].nil?
+
+ opts[:make_default] = false if opts[:make_default].nil?
+
+ id = JSS::Printer.valid_id identifier, api: @api
+ raise JSS::NoSuchItemError, "No printer matches '#{identifier}'" unless id
+ id
+ end
+
def rest_xml
doc = REXML::Document.new APIConnection::XML_HEADER
obj = doc.add_element RSRC_OBJECT_KEY.to_s
general = obj.add_element 'general'
@@ -1473,10 +1812,26 @@
maint.add_element('byhost').text = @fix_byhost.to_s
maint.add_element('system_cache').text = @flush_system_cache.to_s
maint.add_element('user_cache').text = @user_cache.to_s
maint.add_element('verify').text = @verify_startup_disk.to_s
+ acct_maint = obj.add_element 'account_maintenance'
+
+ mgmt_acct = acct_maint.add_element 'management_account'
+ JSS.hash_to_rexml_array(@management_account).each { |x| mgmt_acct << x }
+
+ directory_bindings = acct_maint.add_element 'directory_bindings'
+ @directory_bindings.each do |b|
+ directory_binding = directory_bindings.add_element 'binding'
+ dbdeets = JSS.hash_to_rexml_array b
+ dbdeets.each { |d| directory_binding << d }
+ end
+
+ user_interaction = obj.add_element 'user_interaction'
+ user_interaction.add_element('message_start').text = @user_message_start.to_s
+ user_interaction.add_element('message_finish').text = @user_message_finish.to_s
+
files_processes = obj.add_element 'files_processes'
JSS.hash_to_rexml_array(@files_processes).each { |f| files_processes << f }
pkg_conf = obj.add_element 'package_configuration'
pkgs = pkg_conf.add_element 'packages'
@@ -1489,9 +1844,29 @@
scripts = obj.add_element 'scripts'
@scripts.each do |s|
script = scripts.add_element 'script'
sdeets = JSS.hash_to_rexml_array s
sdeets.each { |d| script << d }
+ end
+
+ disk_encryption = obj.add_element 'disk_encryption'
+
+ @disk_encryption.each do |k,v|
+ disk_encryption.add_element(k.to_s).text = v.to_s
+ end
+
+ printers = obj.add_element 'printers'
+ @printers.each do |pr|
+ printer = printers.add_element 'printer'
+ pdeets = JSS.hash_to_rexml_array pr
+ pdeets.each { |d| printer << d }
+ end
+
+ dock_items = obj.add_element 'dock_items'
+ @dock_items.each do |d|
+ dock_item = dock_items.add_element 'dock_item'
+ ddeets = JSS.hash_to_rexml_array d
+ ddeets.each { |de| dock_item << de }
end
add_self_service_xml doc
add_site_to_xml doc