app/models/mixins/miq_policy_mixin.rb
module MiqPolicyMixin
extend ActiveSupport::Concern
included do
tag_attribute :policy, "/miq_policy/assignment"
end
def add_policy(policy)
ns = "/miq_policy"
cat = "assignment/#{policy.class.to_s.underscore}"
tag = policy.id.to_s
tag_add(tag, :ns => ns, :cat => cat)
reload
end
def remove_policy(policy)
ns = "/miq_policy"
cat = "assignment/#{policy.class.to_s.underscore}"
tag = policy.id.to_s
tags = tag_list(:ns => ns, :cat => cat).split
tags.delete(tag)
tag_with(tags.join(" "), :ns => ns, :cat => cat)
reload
end
def get_policies
policy_tags
.map { |t| t.split("/").first(2) }
.group_by(&:first)
.select { |klass, _ids| ["miq_policy", "miq_policy_set"].include?(klass) }
.flat_map { |klass, ids| klass.camelize.constantize.where(:id => ids.map(&:last)).to_a }
end
def resolve_policies(list, event = nil)
MiqPolicy.resolve(self, list, event)
end
def resolve_profiles(list, event = nil)
result = []
list.each do |pid|
prof = MiqPolicySet.find(pid)
next unless prof
plist = prof.members.collect(&:name)
presults = resolve_policies(plist, event)
next if presults.empty? # skip profiles that had no policies due to the event not matching or no policies in scope
prof_result = "allow"
presults.each do |r|
if r["result"] == "deny"
prof_result = "deny"
break
end
end
result_list = presults.collect { |r| r["result"] }.uniq
prof_result = result_list.first if result_list.length == 1 && result_list.first == "N/A"
result.push(prof.attributes.merge("result" => prof_result, "policies" => presults))
end
result
end
def passes_policy?(list = nil)
list.nil? ? plist = policies : plist = resolve_policies(list)
result = true
plist.each do |policy|
result = false if policy["result"] == "deny"
end
result_list = plist.collect { |r| r["result"] }.uniq
result = result_list.first if result_list.length == 1 && result_list.first == "N/A"
result
end
def passes_profiles?(list)
plist = resolve_profiles(list)
result = true
plist.each do |prof|
result = false if prof["result"] == "deny"
end
result_list = plist.collect { |r| r["result"] }.uniq
result = result_list.first if result_list.length == 1 && result_list.first == "N/A"
result
end
def parent_enterprise
MiqEnterprise.my_enterprise
end
# cb_method: the MiqQueue callback method along with the parameters that is called
# when automate process is done and the request is not prevented to proceed by policy
def prevent_callback_settings(*cb_method)
{
:class_name => self.class.to_s,
:instance_id => id,
:method_name => :check_policy_prevent_callback,
:args => [*cb_method],
:server_guid => MiqServer.my_guid
}
end
def check_policy_prevent_callback(*action, _status, _message, result)
prevented = false
if result.kind_of?(MiqAeEngine::MiqAeWorkspaceRuntime)
event = result.get_obj_from_path("/")['event_stream']
data = event.attributes["full_data"]
prevented = data.fetch_path(:policy, :prevented) if data
end
if prevented
_log.info(event.attributes["message"])
else
kwargs = action.extract_options!
send(*action, **kwargs)
end
end
module ClassMethods
def rsop(event, targets)
eventobj = event.kind_of?(String) ? MiqEventDefinition.find_by(:name => event) : MiqEventDefinition.extract_objects(event)
raise _("No event found for [%{event}]") % {:event => event} if eventobj.nil?
targets = extract_objects(targets)
result = []
targets.each do |t|
profiles = (t.get_policies + MiqPolicy.associations_to_get_policies.collect do |assoc|
next unless t.respond_to?(assoc)
t.send(assoc).get_policies unless t.send(assoc).nil?
end).compact.flatten.uniq
presults = t.resolve_profiles(profiles.collect(&:id), eventobj)
target_result = presults.inject("allow") do |s, r|
break "deny" if r["result"] == "deny"
s
end
result_list = presults.collect { |r| r["result"] }.uniq
target_result = result_list.first if result_list.length == 1 && result_list.first == "N/A"
result.push("id" => t.id, "name" => t.name, "result" => target_result, "profiles" => presults)
end
result
end
def rsop_async(event, targets, userid = nil)
eventobj = event.kind_of?(String) ? MiqEventDefinition.find_by(:name => event) : MiqEventDefinition.extract_objects(event)
raise _("No event found for [%{event}]") % {:event => event} if eventobj.nil?
targets = targets.collect(&:id) if targets.first.kind_of?(self)
opts = {
:action => "#{name} - Resultant Set of Policy, Event: [#{eventobj.description}]",
:userid => userid
}
qopts = {
:class_name => name,
:method_name => "rsop",
:args => [eventobj.name, targets],
:priority => MiqQueue::HIGH_PRIORITY
}
MiqTask.generic_action_with_callback(opts, qopts)
end
end # module ClassMethods
end # module MiqPolicyMixin