diff --git a/cost/azure/unused_ip_addresses/CHANGELOG.md b/cost/azure/unused_ip_addresses/CHANGELOG.md index 8d9899bd28..7fa06c68d4 100644 --- a/cost/azure/unused_ip_addresses/CHANGELOG.md +++ b/cost/azure/unused_ip_addresses/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v7.1 + +- Added IP allocation type (Dynamic or Static) to incident output +- Added ability to filter results by allocation type via parameter +- Added ability to filter results by minimum savings via parameter + ## v7.0 - Added support for regex when filtering resources by tag diff --git a/cost/azure/unused_ip_addresses/README.md b/cost/azure/unused_ip_addresses/README.md index 26589fd4d8..57a6e89d15 100644 --- a/cost/azure/unused_ip_addresses/README.md +++ b/cost/azure/unused_ip_addresses/README.md @@ -36,7 +36,9 @@ This policy has the following input parameters required when launching the polic - *Email Addresses* - Email addresses of the recipients you wish to notify. - *Azure Endpoint* - Select the API endpoint to use for Azure. Use default value of management.azure.com unless using Azure China. +- *Minimum Savings Threshold* - Minimum potential savings required to generate a recommendation. - *Days Unattached* - The number of days an IP address needs to be detached to be considered unused. This value cannot be set above 90 due to Azure only storing 90 days of log data. If this value is set to 0, all unattached IP addresses will be considered unused. +- *Allocation Type* - Whether to include only Dynamic IPs in the results, only Static IPs, or both. - *Allow/Deny Subscriptions* - Whether to treat Allow/Deny Subscriptions List parameter as allow or deny list. Has no effect if Allow/Deny Subscriptions List is left empty. - *Allow/Deny Subscriptions List* - Filter results by subscription ID/name, either only allowing this list or denying it depending on how the above parameter is set. Leave blank to consider all the subscriptions. - *Allow/Deny Regions* - Whether to treat Allow/Deny Regions List parameter as allow or deny list. Has no effect if Allow/Deny Regions List is left empty. diff --git a/cost/azure/unused_ip_addresses/azure_unused_ip_addresses.pt b/cost/azure/unused_ip_addresses/azure_unused_ip_addresses.pt index 7dd96cc55d..b8502a3140 100644 --- a/cost/azure/unused_ip_addresses/azure_unused_ip_addresses.pt +++ b/cost/azure/unused_ip_addresses/azure_unused_ip_addresses.pt @@ -6,7 +6,7 @@ severity "low" category "Cost" default_frequency "weekly" info( - version: "6.3", + version: "7.1", provider: "Azure", service: "Compute", policy_set: "Unused IP Addresses", @@ -34,6 +34,15 @@ parameter "param_azure_endpoint" do default "management.azure.com" end +parameter "param_min_savings" do + type "number" + category "Policy Settings" + label "Minimum Savings Threshold" + description "Minimum potential savings required to generate a recommendation" + min_value 0 + default 0 +end + parameter "param_days_unattached" do type "number" category "Policy Settings" @@ -44,6 +53,15 @@ parameter "param_days_unattached" do max_value 90 end +parameter "param_allocation_type" do + type "string" + category "Filters" + label "Allocation Type" + description "Whether to include only Dynamic IPs in the results, only Static IPs, or both." + allowed_values "Dynamic", "Static", "Both" + default "Both" +end + parameter "param_subscriptions_allow_or_deny" do type "string" category "Filters" @@ -315,12 +333,30 @@ datasource "ds_ip_addresses" do end end +datasource "ds_ip_addresses_alloc_filtered" do + run_script $js_ip_addresses_alloc_filtered, $ds_ip_addresses, $param_allocation_type +end + +script "js_ip_addresses_alloc_filtered", type: "javascript" do + parameters "ds_ip_addresses", "param_allocation_type" + result "result" + code <<-EOS + if (param_allocation_type != "Both") { + result = _.filter(ds_ip_addresses, function(ip) { + return ip['properties']['publicIPAllocationMethod'] == param_allocation_type + }) + } else { + result = ds_ip_addresses + } +EOS +end + datasource "ds_ip_addresses_tag_filtered" do - run_script $js_ip_addresses_tag_filtered, $ds_ip_addresses, $param_exclusion_tags, $param_exclusion_tags_boolean + run_script $js_ip_addresses_tag_filtered, $ds_ip_addresses_alloc_filtered, $param_exclusion_tags, $param_exclusion_tags_boolean end script "js_ip_addresses_tag_filtered", type: "javascript" do - parameters "ds_ip_addresses", "param_exclusion_tags", "param_exclusion_tags_boolean" + parameters "ds_ip_addresses_alloc_filtered", "param_exclusion_tags", "param_exclusion_tags_boolean" result "result" code <<-EOS comparators = _.map(param_exclusion_tags, function(item) { @@ -354,7 +390,7 @@ script "js_ip_addresses_tag_filtered", type: "javascript" do }) if (param_exclusion_tags.length > 0) { - result = _.reject(ds_ip_addresses, function(resource) { + result = _.reject(ds_ip_addresses_alloc_filtered, function(resource) { resource_tags = {} if (typeof(resource['tags']) == 'object') { resource_tags = resource['tags'] } @@ -387,7 +423,7 @@ script "js_ip_addresses_tag_filtered", type: "javascript" do return all_tags_found || any_tags_found }) } else { - result = ds_ip_addresses + result = ds_ip_addresses_alloc_filtered } EOS end @@ -663,11 +699,11 @@ EOS end datasource "ds_ip_cost_mapping" do - run_script $js_ip_cost_mapping, $ds_unused_ip_addresses, $ds_ip_addresses_region_filtered, $ds_ip_costs_grouped, $ds_applied_policy, $ds_currency, $param_days_unattached + run_script $js_ip_cost_mapping, $ds_unused_ip_addresses, $ds_ip_addresses_region_filtered, $ds_ip_costs_grouped, $ds_applied_policy, $ds_currency, $param_days_unattached, $param_min_savings end script "js_ip_cost_mapping", type:"javascript" do - parameters "ds_unused_ip_addresses", "ds_ip_addresses_region_filtered", "ds_ip_costs_grouped", "ds_applied_policy", "ds_currency", "param_days_unattached" + parameters "ds_unused_ip_addresses", "ds_ip_addresses_region_filtered", "ds_ip_costs_grouped", "ds_applied_policy", "ds_currency", "param_days_unattached", "param_min_savings" result "result" code <<-'EOS' // Function for formatting currency numbers later @@ -700,50 +736,53 @@ script "js_ip_cost_mapping", type:"javascript" do savings = 0.0 } - total_savings += savings + if (savings >= param_min_savings) { + total_savings += savings - ip_message = '' + ip_message = '' - if (typeof(ip['properties']['ipAddress']) == 'string') { - ip_message = "(" + ip['properties']['ipAddress'] + ") " - } + if (typeof(ip['properties']['ipAddress']) == 'string') { + ip_message = "(" + ip['properties']['ipAddress'] + ") " + } - recommendationDetails = [ - "Delete IP address ", ip["resourceName"], " ", ip_message, - "in Azure Subscription ", ip["subscriptionName"], - " (", ip["subscriptionID"], ")" - ].join('') + recommendationDetails = [ + "Delete IP address ", ip["resourceName"], " ", ip_message, + "in Azure Subscription ", ip["subscriptionName"], + " (", ip["subscriptionID"], ")" + ].join('') + + tags = [] - tags = [] + if (typeof(ip['tags']) == 'object') { + _.each(Object.keys(ip['tags']), function(key) { + tags.push([key, "=", ip['tags'][key]].join('')) + }) + } - if (typeof(ip['tags']) == 'object') { - _.each(Object.keys(ip['tags']), function(key) { - tags.push([key, "=", ip['tags'][key]].join('')) + result.push({ + accountID: ip["subscriptionID"], + accountName: ip["subscriptionName"], + resourceID: ip['resourceID'], + resourceName: ip['resourceName'], + resourceGroup: ip['resourceGroup'], + resourceType: ip['resourceType'], + ipAddress: ip['properties']['ipAddress'], + allocation: ip['properties']['publicIPAllocationMethod'], + region: ip['region'], + service: ip['service'], + age: ip['age'], + tags: tags.join(', '), + savings: parseFloat(savings.toFixed(3)), + savingsCurrency: ds_currency['symbol'], + recommendationDetails: recommendationDetails, + lookbackPeriod: param_days_unattached, + service: "Microsoft.Network", + // These are to avoid errors when we hash_exclude these fields + total_savings: '', + message: '', + policy_name: '' }) } - - result.push({ - accountID: ip["subscriptionID"], - accountName: ip["subscriptionName"], - resourceID: ip['resourceID'], - resourceName: ip['resourceName'], - resourceGroup: ip['resourceGroup'], - resourceType: ip['resourceType'], - ipAddress: ip['properties']['ipAddress'], - region: ip['region'], - service: ip['service'], - age: ip['age'], - tags: tags.join(', '), - savings: parseFloat(savings.toFixed(3)), - savingsCurrency: ds_currency['symbol'], - recommendationDetails: recommendationDetails, - lookbackPeriod: param_days_unattached, - service: "Microsoft.Network", - // These are to avoid errors when we hash_exclude these fields - total_savings: '', - message: '', - policy_name: '' - }) }) // Message for incident output @@ -847,6 +886,9 @@ policy "pol_unused_ip_addresses" do field "region" do label "Region" end + field "allocation" do + label "Allocation" + end field "tags" do label "Tags" end diff --git a/cost/azure/unused_ip_addresses/azure_unused_ip_addresses_meta_parent.pt b/cost/azure/unused_ip_addresses/azure_unused_ip_addresses_meta_parent.pt index 27d15c3b07..f2c77b1f75 100644 --- a/cost/azure/unused_ip_addresses/azure_unused_ip_addresses_meta_parent.pt +++ b/cost/azure/unused_ip_addresses/azure_unused_ip_addresses_meta_parent.pt @@ -8,7 +8,7 @@ tenancy "single" default_frequency "15 minutes" info( provider: "Azure", - version: "6.3", # This version of the Meta Parent Policy Template should match the version of the Child Policy Template as it appears in the Catalog for best reliability + version: "7.1", # This version of the Meta Parent Policy Template should match the version of the Child Policy Template as it appears in the Catalog for best reliability publish: "false" ) @@ -77,6 +77,15 @@ parameter "param_azure_endpoint" do default "management.azure.com" end +parameter "param_min_savings" do + type "number" + category "Policy Settings" + label "Minimum Savings Threshold" + description "Minimum potential savings required to generate a recommendation" + min_value 0 + default 0 +end + parameter "param_days_unattached" do type "number" category "Policy Settings" @@ -87,6 +96,15 @@ parameter "param_days_unattached" do max_value 90 end +parameter "param_allocation_type" do + type "string" + category "Filters" + label "Allocation Type" + description "Whether to include only Dynamic IPs in the results, only Static IPs, or both." + allowed_values "Dynamic", "Static", "Both" + default "Both" +end + parameter "param_regions_allow_or_deny" do type "string" category "Filters" @@ -875,6 +893,9 @@ policy "policy_scheduled_report" do field "region" do label "Region" end + field "allocation" do + label "Allocation" + end field "tags" do label "Tags" end