cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Error with Custom Policy

Hi Team,

We were customizing one of the custom policy which exists in flexera i.e Untagged resources. However when we try to apply the policy we were getting several compilation errors. Could you please help us in understanding the basic structure of custom policy. 

Regards

Praful

(4) Replies

Without specific errors it is hard to know where to help, but a good starting point would be reviewing all of the documentation for the Policy Template Language.

 

Below 2 are the errors I am getting 

 

error.PNG

Below is our Policy which we trying to apply 
 
name "Untagged Resources"
rs_pt_ver 20180301
type "policy"
short_description "Check resources for missing tags and report on them. \n See the [README](https://github.com/rightscale/policy_templates/tree/master/compliance/tags/tag_checker) and [docs.flexera.com/flexera/EN/Automation](https://docs.flexera.com/flexera/EN/Automation/AutomationGS.htm) to learn more."
long_description ""
category "Compliance"
severity "medium"
info(
  version: "1.14",
  provider: "Flexera Cloud Management",
  service: "",
  policy_set: ""
)

permission "retrieve_resources" do
  label "Retrieve Resources"
  actions   "rs_cm.index","rs_cm.show"
  resources "rs_cm.instances","rs_cm.volumes"
end

permission "tags" do
  label "Retrieve and add Tags"
  actions "rs_cm.by_resource","rs_cm.multi_add"
  resources "rs_cm.tags"
end

##################
# User inputs    #
##################
parameter "param_tag_keys" do
  category "User Inputs"
  label "Tags' Namespace:Keys List"
  type "string"
  description "Comma-separated list of Tags' Namespace:Keys to audit. For example: \"ec2:project_code\" or \"bu:id\"."
  # allow namespace:key or nothing
  allowed_pattern /^([a-zA-Z0-9-_]+:[a-zA-Z0-9-_]+,*|)+$/
end

parameter "param_advanced_tag_key" do
  category "User Inputs"
  label "Tags' Namespace:Keys Advanced List"
  type "string"
  description 'A JSON string to describe the tag policy configuration.  See the README for example'
  allowed_pattern /(\{.*\}|)/
end

parameter "param_email" do
  label "Email addresses of the recipients you wish to notify"
  type "list"
end

# Retrieve all clouds
resources "clouds", type: "rs_cm.clouds"
# Retrieve all operational instances across all clouds
resources "instances_operational", type: "rs_cm.instances" do
  iterate @clouds
  cloud_href href(iter_item)
  filter do
    state "operational"
  end
  tags '*'
end
# Retrieve all provisioned instances across all clouds
resources "instances_provisioned", type: "rs_cm.instances" do
  iterate @clouds
  cloud_href href(iter_item)
  filter do
    state "provisioned"
  end
  tags '*'
end

# Retrieve all running instances across all clouds
resources "instances_running", type: "rs_cm.instances" do
  iterate @clouds
  cloud_href href(iter_item)
  filter do
    state "running"
  end
  tags '*'
end

# Retrieve all volumes across all clouds
resources "volumes", type: "rs_cm.volumes" do
  iterate @clouds
  cloud_href href(iter_item)
  tags '*'
end

datasource "clouds" do
  iterate @clouds
  field "href",         href(iter_item)
  field "type",         val(iter_item,'cloud_type')
  field "name",         val(iter_item,'name')
end

datasource "instances_operational" do
  iterate @instances_operational
  field "href",        href(iter_item)
  field "id",          val(iter_item,'resource_uid')
  field "name",        val(iter_item,'name')
  field "state",       val(iter_item,'state')
  field "tags",         val(iter_item,'tags')
  field "type",        "instances"
end
datasource "instances_running" do
  iterate @instances_running
  field "href",        href(iter_item)
  field "id",          val(iter_item,'resource_uid')
  field "name",        val(iter_item,'name')
  field "state",       val(iter_item,'state')
  field "tags",         val(iter_item,'tags')
  field "type",        "instances"
end
datasource "instances_provisioned" do
  iterate @instances_provisioned
  field "href",        href(iter_item)
  field "id",          val(iter_item,'resource_uid')
  field "name",        val(iter_item,'name')
  field "state",       val(iter_item,'state')
  field "tags",        val(iter_item,'tags')
  field "type",        "instances"
end

datasource "volumes" do
  iterate @volumes
  field "href",        href(iter_item)
  field "id",          val(iter_item,'resource_uid')
  field "name",        val(iter_item,'name')
  field "state",       val(iter_item,'status')
  field "tags",        val(iter_item,'tags')
  field "type",        "volumes"
end


datasource "resources" do
  run_script $merge_resources, $instances_operational,$instances_running,$instances_provisioned,$volumes
end

script "merge_resources", type: "javascript" do
  parameters "instances_operational","instances_running","instances_provisioned", "volumes"
  result "resources"
  code <<-EOS
    var resources = []
    for (i = 0; i < instances_operational.length; i++) {
      resources.push(instances_operational[i])
    }
    for (i = 0; i < instances_running.length; i++) {
      resources.push(instances_running[i])
    }
    for (i = 0; i < instances_provisioned.length; i++) {
      resources.push(instances_provisioned[i])
    }
    for (i = 0; i < volumes.length; i++) {
      resources.push(volumes[i])
    }
  EOS
end

auth "rs", type: "rightscale"

# get a tagset for all resources
datasource "resource_tags" do
  request do
    auth $rs
    verb "POST"
    host rs_cm_host
    path "/api/tags/by_resource"
    header "X-Api-Version", "1.5"
    body_field "resource_hrefs", vals($resources,"href")
  end
end

datasource "filtered_resources" do
  run_script $filter_resources, $resources, $clouds,$param_tag_keys,$param_advanced_tag_key
end


script "filter_resources", type: "javascript" do
  parameters "resources","clouds","param_tag_keys","param_advanced_tag_key"
  result "filtered_resources"
  code <<-EOS
// This is the list of filtered volumes.
var filtered_resources = [];
var tag_keys_array = []
if ( param_tag_keys !== '' ){
  tag_keys_array = param_tag_keys.split(',')
}
var validate_tags_object={}
// keys from JSON
var advanced_tag_keys=[]
// check for param_advanced_tag_key and parse the json
if ( param_advanced_tag_key !== '') {
  validate_tags_object = JSON.parse(param_advanced_tag_key)
  advanced_tag_keys = _.keys(validate_tags_object)
  for (var i = 0; i < advanced_tag_keys.length; i++) {
    tag_keys_array.push(advanced_tag_keys[i])
  }
}
tag_keys_array = _.uniq(tag_keys_array)
// create a map of clouds with href key to get type and name
var cloud_map = {}
for (var i = 0; i < clouds.length; i++) {
    var cloud = clouds[i]
    cloud_map[cloud['href']]={'type': cloud['type'],'name': cloud['name']}
}
// Go through all the resources and filter the ones that don't
// comply with the tag rules.
for (var i = 0; i < resources.length; i++) {
  var res = resources[i]
  var res_tags = []
  var invalid_tags =[]
  var bad = false
  // Tags is an array of hashes each with just 'name'. Let's convert
  // them to an array of strings.
  for (var j = 0; j < res['tags'].length; j++) {
    tag = res['tags'][j]
    tag_key = tag.split("=")[0]
    tag_value = tag.split("=")[1]
    if ( validate_tags_object[tag_key] && validate_tags_object[tag_key]['validation-type']==='string' ){
      if ( validate_tags_object[tag_key]['validation'] !== tag_value ){
        bad=true
        invalid_tags.push(tag)
      }
    }
    if ( validate_tags_object[tag_key] && validate_tags_object[tag_key]['validation-type'] === 'array' ){
      if ( validate_tags_object[tag_key]['validation'].indexOf(tag_value) === -1 ){
        bad=true
        invalid_tags.push(tag)
      }
    }
    if ( validate_tags_object[tag_key] && validate_tags_object[tag_key]['validation-type'] === 'regex'){
      if ( tag_value.search(validate_tags_object[tag_key]['validation']) === -1 ){
        bad=true
        invalid_tags.push(tag)
      }
    }
    res_tags.push(tag_key)
  }
  // Determines whether this resource is properly tagged
  var missing_tags = []
  if ( _.intersection(tag_keys_array, res_tags).length != tag_keys_array.length ) {
    bad = true;
    //find the tags missing from the resource
    missing_tags=_.difference(tag_keys_array, res_tags)
  }
  // create cloud_href from resource href
  var split = res['href'].split('/')
  var index = res['href'].indexOf('/'+split[4])
  var cloud_href = res['href'].substring(0,index)
  // update resource array with resources that are missing tags
  if ( bad ) {
    var missing_tags_list = "";
    var invalid_tags_list = "";
    for(var prop in missing_tags){
      missing_tags_list = missing_tags_list +prop+":"+missing_tags[prop]+", "
    }
    for(var prop in invalid_tags){
      invalid_tags_list = invalid_tags_list+prop+":"+invalid_tags[prop]+", "
    }
    filtered_resources.push({
      id: res['id'],
      name: res['name'],
      state: res['state'],
      href: res['href'],
      type: res['type'],
      cloud_name: cloud_map[cloud_href]['name'],
      cloud_type: cloud_map[cloud_href]['type'],
      missing_tags: missing_tags,
      invalid_tags: invalid_tags,
    })
  }
};
  EOS
end

escalation "email" do
  automatic true
  label "Send Email"
  description "Send incident email"
  email $param_email
end

policy "untagged_resources_policy" do
  validate $filtered_resources do
    summary_template "{{ rs_project_name }} (Account ID: {{ rs_project_id }}): {{ len data }} Untagged Resources Found"

    export do
      resource_level true
      field "cloud_name" do
        label "Cloud Name"
      end
      field "cloud_type" do
        label "Cloud Type"
      end
      field "name" do
        label "Name"
      end
      field "type" do
        label "Type"
      end
      field "state" do
        label "State"
      end
      field "href" do
        label "Href"
      end
      field "missing_tags" do
        label "Missing Tags"
      end
      field "invalid_tags" do
        label "Invalid Tags"
      end
      field "id" do
        label "ID"
      end
    end

    escalate $escalate_resources
    escalate $email
    check eq(size(data), 0)
    resolve $resolve_resources
  end
end

define sys_log($subject, $detail) do
  if $$debug
    rs_cm.audit_entries.create(
      notify: "None",
      audit_entry: {
        auditee_href: @@account,
        summary: "Untagged Resources Policy "+ $subject,
        detail: $detail
      }
    )
  end
end

As the errors you pasted state, the escalation and resolve references that are on those lines are not defined elsewhere in the Policy Template. You need to have escalation declarations for both of them, something like:

escalation "escalate_resources" do
  ...
end

resolution "resolve_resources" do
  ...
end